题意:给G个女孩和B个男孩的关系,要选出一个最大集合,集合中两两都认识。注意数据范围是男女各两百,所以点有400.。。
建反图,那么求出的子集就需要两两都不认识,从而等价于求最大独立集的大小。根据定理|最大独立集合|+|最小顶点覆盖|=|V|,又可转化为求最小顶点覆盖,从而求出完美匹配数即可,用匈牙利算法~顺便给自己留个板子
代码
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX = 512;
bool vis[MAX];
int match[MAX];
int G[MAX][MAX];
bool dfs(int u, int n) {
for (int i = 1; i <= n; ++i) {
if (!vis[i] && G[u][i]) {
vis[i] = true;
if (match[i] == -1 || dfs(match[i], n)) {
match[i] = u;
return true;
}
}
}
return false;
}
inline int read() {
char ch;
while ((ch = getchar()) < '0' || ch > '9');
int x = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + ch - '0';
}
return x;
}
int main() {
int Girl, Boy, Met;
while (~scanf(" %d %d %d", &Girl, &Boy, &Met)) {
if (Girl == 0 && Boy == 0 && Met == 0) break;
int n = Girl + Boy;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
G[i][j] = 1;
}
}
int u, v;
while (Met--) {
u = read();
v = read();
G[u][v] = 0;
}
memset(match, -1, sizeof(match));
int tot = 0;
for (int i = 1; i <= Girl; ++i) {
memset(vis, false, sizeof(vis));
if (dfs(i, Boy)) {
++tot;
//printf("%d\n", i);
}
}
static int cas = 0;
printf("Case %d: %d\n", ++cas, n - tot);
}
return 0;
}