hdu 3081(二分+最大流+并查集)

来源:互联网 发布:外交官 新秀丽 知乎 编辑:程序博客网 时间:2024/05/21 09:43

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081

思路设源点为0,汇点为2*n+1,对没吵过架的女生和男生连容量为1的边(这里要用到并查集,每个女生的朋友也可以和该男生连边),然后就是源点与女生连边,容量为mid(0<=mid<=n),男生与汇点也连容量为mid的边(这里的mid即为为每个男孩和女孩找到了k个不同的伴侣,说明游戏可以进行k轮,附上链接:http://blog.csdn.net/qq564690377/article/details/7857983),然后就是二分搜索了。

View Code
  1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 using namespace std;  5 #define MAXN 222  6 #define inf 1<<30  7 int map[MAXN][MAXN];  8 int mm[MAXN][MAXN];  9 int pre[MAXN]; 10 int level[MAXN]; 11 int gap[MAXN]; 12 int parent[MAXN]; 13 int NV,n,m,f; 14  15 void Initiate(){ 16     for(int i=1;i<=2*n;i++){ 17         parent[i]=-1; 18     } 19 } 20  21 int Find(int x){ 22     int s; 23     for(s=x;parent[s]>0;s=parent[s]) 24         ; 25     while(x!=s){ 26         int tmp=parent[x]; 27         parent[x]=s; 28         x=tmp; 29     } 30     return s; 31 } 32  33 void Union(int u,int v){ 34     int r1=Find(u); 35     int r2=Find(v); 36     if(r1==r2)return ; 37     if(parent[r1]>parent[r2]){ 38         parent[r2]+=parent[r1]; 39         parent[r1]=r2; 40     }else { 41         parent[r1]+=parent[r2]; 42         parent[r2]=r1; 43     } 44 } 45  46  47 int SAP(int vs,int vt){ 48     memset(pre,-1,sizeof(pre)); 49     memset(level,0,sizeof(level)); 50     memset(gap,0,sizeof(gap)); 51     int v,u=pre[vs]=vs,maxflow=0,aug=inf; 52     gap[0]=NV; 53     while(level[vs]<NV){ 54         for(v=1;v<=vt;v++){ 55             if(map[u][v]&&level[u]==level[v]+1){ 56                 break; 57             } 58         } 59         if(v<=vt){ 60             pre[v]=u; 61             u=v; 62             if(v==vt){ 63                 aug=inf; 64                 for(int i=v;i!=vs;i=pre[i]){ 65                     if(aug>map[pre[i]][i])aug=map[pre[i]][i]; 66                 } 67                 maxflow+=aug; 68                 for(int i=v;i!=vs;i=pre[i]){ 69                     map[pre[i]][i]-=aug; 70                     map[i][pre[i]]+=aug; 71                 } 72                 u=vs; 73             } 74         }else { 75             int minlevel=NV; 76             for(int v=1;v<=vt;v++){ 77                 if(map[u][v]&&minlevel>level[v]){ 78                     minlevel=level[v]; 79                 } 80             } 81             gap[level[u]]--; 82             if(gap[level[u]]==0)break; 83             level[u]=minlevel+1; 84             gap[level[u]]++; 85             u=pre[u]; 86         } 87     } 88     return maxflow; 89 } 90  91 void Build(int k){ 92     memset(map,0,sizeof(map)); 93     for(int i=1;i<=n;i++){ 94         map[0][i]=k; 95         map[i+n][2*n+1]=k; 96     } 97     for(int i=1;i<=n;i++){ 98         for(int j=n+1;j<=2*n;j++){ 99             map[i][j]=mm[i][j];100         }101     }102     for(int i=1;i<=n;i++){103         for(int j=1;j<=n;j++){104             if(Find(i)==Find(j)){105                 for(int k=n+1;k<=2*n;k++){106                     if(map[i][k])map[j][k]=1;107                 }108             }109         }110     }111 }112 113 114 int Binary_Search(){115     int low=0,high=n,tmp;116     NV=2*n+2;117     while(low<=high){118         int mid=(low+high)/2;119         Build(mid);120         if(mid*n==SAP(0,2*n+1)){121             tmp=mid;//这里需要保留mid值。122             low=mid+1;123         }else 124             high=mid-1;125     }126     return tmp;127 }128 129 130 int main(){131     int _case,g,b,g1,g2;132     scanf("%d",&_case);133     while(_case--){134         scanf("%d%d%d",&n,&m,&f);135         Initiate();136         memset(map,0,sizeof(map));137         memset(mm,0,sizeof(mm));138         for(int i=1;i<=m;i++){139             scanf("%d%d",&g,&b);140             map[g][b+n]=1;141             mm[g][b+n]=1;//保留原图,因为每次SAP之后,图就改变了。142         }143         for(int i=1;i<=f;i++){144             scanf("%d%d",&g1,&g2);145             if(Find(g1)!=Find(g2)){146                 Union(g1,g2);147             }148         }149         int ans=Binary_Search();150         printf("%d\n",ans);151     }152     return 0;153 }154 155         156 157 158 159             

 

0 0