题目大概意思为有G个女生和B个男生,每个男生都相互认识,每个女生也相互认识,部分男生与部分女生相互认识,求最大相互认识的点集
题目很简单,只用稍微转换一下思路即可,因为我们要以男生与女生来构建二分图,所以所有边都应该连接男生和女生,因此男生与男生和女生与女生之间不应该有边相连。
因此我们以两人互不相识为条件构建边,这样就能得到一个二分图。
然后因为两点之间没有线等于两人认识,所以我们求的 |最大互相认识的点集| = |最大独立集|
有公式 : |最大独立集| + |最小顶点覆盖| = |所有顶点集|
二分图中 |最小顶点覆盖| = |最大匹配|
所以 |最大互相认识的点集| = |最大独立集| = |所有顶点集| - |最小顶点覆盖| = |所有顶点集| - |最大匹配|
(一道基础题 )
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
using namespace std;
vector<int> data[205];
bool ddd[205][205];
int match[205];
bool used[205];
void add_edge(int from, int to)
{
data[from].push_back(to);
}
bool dfs(int v)
{
used[v] = true;
for(int i = 0; i < data[v].size(); i++)
{
int u = data[v][i], w = match[u];
if(w < 0 || !used[w] && dfs(w))
{
match[u] = v;
return true;
}
}
return false;
}
int main()
{
int flag = 1;
while(1)
{
memset(ddd, false, sizeof(ddd));
int G, B, M;
scanf("%d %d %d", &G, &B, &M);
if(G == 0 && B == 0 && M == 0)
{
break;
}
for(int i = 0; i < G; i++)
{
data[i].clear();
}
for(int i = 0; i < M; i++)
{
int from, to;
scanf("%d %d", &from, &to);
ddd[from-1][to-1] = true;
}
for(int i = 0; i < G; i++)
{
for(int j = 0; j < B; j++)
{
if(!ddd[i][j])
{
add_edge(i, j);
}
}
}
memset(match, -1, sizeof(match));
int res = 0;
for(int i = 0; i < G; i++)
{
memset(used, 0, sizeof(used));
if(dfs(i))
{
res++;
}
}
printf("Case %d: %d\n", flag, G + B - res);
flag++;
}
}