hdu 308

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

你可能感兴趣的:(hdu 308)