一个幼儿园里女生相互认识,男生也相互认识,另外有些男生女生相互认识,老师要带一群相互认识的孩子,问最大数量。
由于女生相互认识,男生相互认识,因此这个图的补图一定为二分图,于是就把这个图转换而求补图的最大独立集。
补图中不认识就代表了在原图中相互认识。
#include <cstdio>
#include <cstring>
#include <vector>
const int maxn = 200 + 2;
const int maxv = 2 * maxn;
int G1[maxn][maxn];
int V;
std::vector<int> G2[maxv];
int match[maxv];
bool used[maxv];
void add_edge(int u, int v) {
G2[u].push_back(v);
G2[v].push_back(u);
}
bool dfs(int v) {
used[v] = true;
for (int i = 0; i < G2[v].size(); i++) {
int u = G2[v][i], w = match[u];
if (w < 0 || (!used[w] && dfs(w))) {
match[u] = v;
match[v] = u;
return true;
}
}
return false;
}
int Hungarian() {
int res = 0;
memset(match, -1, sizeof(match));
for (int v = 0; v < V; v++) {
if (match[v] < 0) {
memset(used, 0, sizeof(used));
if (dfs(v)) {
res++;
}
}
}
return res;
}
int main() {
int t = 1;
int g, b, m;
while (scanf("%d%d%d", &g, &b, &m) == 3 && g + b + m) {
V = g + b;
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v);
G1[u-1][v-1] = 1;
}
for (int i = 0; i < g; i++) {
for (int j = 0; j < b; j++) {
if (!G1[i][j]) {
add_edge(i, j + g);
}
}
}
printf("Case %d: %d\n", t++, V - Hungarian());
for (int i = 0; i < V; i++) {
G2[i].clear();
}
memset(G1, 0, sizeof(G1));
}
return 0;
}