HDU 3081 Marriage Match Il【并查集 + 二分匹配】
题意: 有 2*n个同学,n男n女,知道了 有 m 对 男女之间木有吵过架,现在这 n 个女生要找对象,要求没有和她吵过架或者没有和她的一个朋友吵过架,
当 n 个女生都找到对象的时候算作一轮,然后重新找,满足每个女生都不能找和上次一样的对象,问最多能进行多少轮。
分析: 将是朋友关系的女生放到一个集合,用来降低建图的时间复杂度。
#include <stdio.h> #include <string.h> #define maxn 102 #define clr(x)memset(x,0,sizeof(x)) int f[maxn]; int search(int x) { return f[x] == x?x:(f[x] = search(f[x])); } void join(int x,int y) { int fx = search(x); int fy = search(y); if(fx != fy){ if(fx < fy) f[fy] = fx; else f[fx] = fy; } } int link[maxn]; int v[maxn]; int g[maxn][maxn]; int tt[maxn][maxn]; int n; int find(int x) { int i; for(i = 1; i <= n; i++){ if(g[x][i]&&!v[i]){ v[i] = 1; if(link[i] == 0||find(link[i])){ link[i] = x; return 1; } } } return 0; } struct noql { int girl,boy; }r[maxn*maxn]; int main() { int t; int m, F; int i, j; scanf("%d",&t); while(t--) { scanf("%d %d %d",&n, &m, &F); for(i = 1; i <= n; i++) f[i] = i; clr(g); int a,b; for(i = 1; i <= m; i++) scanf("%d %d",&r[i].girl, &r[i].boy); while(F--){ scanf("%d %d",&a, &b); join(a,b); } for(i = 1; i <= m; i++) g[search(r[i].girl)][r[i].boy] = 1; for(i = 1; i <= n; i++) for(j = 1; j <= n; j++) if(g[search(i)][j] == 1) g[i][j] = 1; int res = 0; while(1){ clr(link); for(i = 1; i <= n; i++){ clr(v); if(!find(i)) break; } if(i != n+1) break; res++; for(i = 1; i <= n; i++) g[link[i]][i] = 0; } printf("%d\n",res); } return 0; }