题目大意:有n个男生n个女生,现在要求将所有的男女配对,所有的男女都配对的话,算该轮游戏结束了。接着另一轮游戏开始,还是男女配对,但是配对的男女不能是之前配对过的。
问这游戏能玩多少轮
男女能配对的条件如下
1.男女未曾吵架过。
2.如果两个女的是朋友,那么另一个女的男朋友可以和该女的配对
解题思路:并查集解决朋友之间的关系,找到能配对的所有情况
接着二分图匹配,找到一个完美匹配算玩了一轮游戏,接着将这完美匹配的边删掉,继续进行匹配
如果无法完美匹配了,表示游戏结束了
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1010
int g[N][N], link[N], vis[N], father[N];
int n, m, f;
int find(int x) {
return x == father[x] ? x : father[x] = find(father[x]);
}
void init() {
scanf("%d%d%d", &n, &m, &f);
memset(g, 0, sizeof(g));
for (int i = 1; i <= n; i++)
father[i] = i;
int x, y;
for (int i = 0; i < m; i++) {
scanf("%d%d", &x, &y);
g[x][y] = 1;
}
for (int i = 0; i < f; i++) {
scanf("%d%d", &x, &y);
father[find(x)] = find(y);
}
for (int i = 1; i <= n; i++) {
int t = find(i);
for (int j = 1; j <= n; j++) {
if (i != j && t == find(j)) {
for (int k = 1; k <= n; k++)
if (g[j][k])
g[i][k] = 1;
}
}
}
}
bool dfs(int u) {
for (int v = 1; v <= n; v++) {
if (!vis[v] && g[u][v]) {
vis[v] = 1;
if (!link[v] || dfs(link[v])) {
link[v] = u;
return true;
}
}
}
return false;
}
void solve() {
int ans = 0;
while (1) {
memset(link, 0, sizeof(link));
int cnt = 0;
for (int i = 1; i <= n; i++) {
memset(vis, 0, sizeof(vis));
if (dfs(i))
cnt++;
}
if (cnt == n) {
ans++;
for (int i = 1; i <= n; i++)
g[link[i]][i] = 0;
}
else
break;
}
printf("%d\n", ans);
}
int main() {
int test;
scanf("%d", &test);
while (test--) {
init();
solve();
}
return 0;
}