题目:http://acm.hdu.edu.cn/showproblem.php?pid=3081
并查集+二分图最大匹配。。关键就是朋友之间的关系处理。。每次找最大匹配。看能否最大匹配==n。删掉匹配过的边。
下面是AC代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 110;
bool g[maxn][maxn];
int match[maxn];
bool vis[maxn];
int fa[maxn];
int p,n;
bool dfs(int cur){
for(int i=1;i<=n;i++){
if(g[cur][i]==true&&!vis[i]){
vis[i]=true;
int t=match[i];
if(t==-1||dfs(t)){
match[i]=cur;
return true;
}
}
}
return false;
}
int hungary(){
int res=0;
for(int i=1;i<=n;i++) match[i]=-1;
for(int i=1;i<=n;i++){
memset(vis,false,sizeof(vis));
if(dfs(i)) res++;
}
return res;
}
int find(int cur){
if(fa[cur]!=cur)
fa[cur]=find(fa[cur]);
return fa[cur];
}
void init(){
int m,f,a,b,c,d;
memset(g,false,sizeof(g));
scanf("%d%d%d",&n,&m,&f);
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
g[b][a]=true;
}
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=0;i<f;i++){
scanf("%d%d",&c,&d);
int pre_c = find(c); int pre_d=find(d);
if(pre_c!=pre_d) fa[pre_c]=pre_d;
}
for(int i=1;i<=n;i++){
int pre_i=find(i);
for(int j=1;j<=n;j++){
if(i!=j&&pre_i==find(j)){
for(int k=1;k<=n;k++)
if(g[k][i]){
g[k][j]=true;
}
}
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
init();
int res=0;
while(1){
if(hungary()==n) res++;
else break;
for(int i=1;i<=n;i++){
g[match[i]][i]=false;
}
}
printf("%d\n",res);
}
return 0;
}