题目: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; }