acm.hdu.edu.cn/showproblem.php?pid=3081
并查集+二分匹配
是朋友关系的女孩合并为一个集合来降低建图的时间复杂度。然后判断最大匹配数是不是n,如果是的话更新图的流量重新匹配,不是的话输出答案。
AC代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int V = 111;
int n,m,f;
int G[V][V];
int check[V],mboy[V],mgirl[V];
int father[V],boy[V*V],girl[V*V];
void Init(){
for(int i=1; i<=n; i++)
father[i] = i;
}
int Find(int x){
if(x != father[x])
father[x] = Find(father[x]);
return father[x];
}
int DFS(int u){
for(int i=1; i<=n; i++){
if(G[u][i] > 0 && !check[i]){
check[i] = 1;
if(mboy[i] == -1 || DFS(mboy[i])){
mgirl[u] = i;
mboy[i] = u;
return 1;
}
}
}
return 0;
}
int MMN(){
int res = 0;
memset(mboy, -1, sizeof(mboy));
memset(mgirl, -1, sizeof(mgirl));
for(int i=1; i<=n; i++){
memset(check, 0, sizeof(check));
res += DFS(i);
}
return res;
}
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
scanf("%d%d%d",&n,&m,&f);
Init();
for(int i=0; i<m; i++)
scanf("%d%d",&girl[i],&boy[i]);
for(int i=0; i<f; i++){
int a,b;
scanf("%d%d",&a,&b);
father[Find(a)] = Find(b);
}
memset(G, 0, sizeof(G));
for(int i=0; i<m; i++)
G[Find(girl[i])][boy[i]] = 1;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
if(G[Find(i)][j])
G[i][j] = 1;
int ans = 0;
while(MMN() == n){
ans++;
for(int i=1; i<=n; i++)
G[i][mgirl[i]] = 0;
}
printf("%d\n",ans);
}
return 0;
}