首页 > 代码库 > HDU 3081 Marriage Match II

HDU 3081 Marriage Match II

http://acm.hdu.edu.cn/showproblem.php?pid=3081

题意:有2N个孩子,其中有N个女生,N个男生,每一个女生可以找一个没有争吵过得男生组成一个家庭,并且可以和与她关系好的女生互换男生。问能交换多少次。

题解:最少交换0次,最多交换2*N次。需要用并查集处理好女生直接的关系。然后二分,建立网络流。

   建边:源点和女生建边,容量为mid;女生和可以交换的男生建边,容量为1;男生和汇点建边,容量为mid。

   可行条件:如果最大流==N*mid,表示可以交换这么多次。

但是不知道为什么在unite()之后还要找一下每一个点的par??为什么???

  1 #include <iostream>  2 #include <cstring>  3 #include <cstdio>  4 #include <cstdlib>  5 #include <cmath>  6 #include <string>  7 #include <vector>  8 #include <list>  9 #include <map> 10 #include <queue> 11 #include <stack> 12 #include <bitset> 13 #include <algorithm> 14 #include <numeric> 15 #include <functional> 16 #include <set> 17 #include <fstream> 18  19 using namespace std; 20  21 const int INF=0xfffffff; 22  23 const int maxn=510; 24 const int maxm=50010; 25  26 struct edge{ 27     int to,next,cap; 28 }G[maxm]; 29 struct node{ 30     int girl,boy; 31 }friend1[maxm]; 32 int judge[maxn][maxn]; 33 int head[maxn],idx,sum; 34 int level[maxn]; 35 int gap[maxn]; 36 int par[maxn]; 37 int rankh[maxn]; 38 int N,M,F; 39 int s,t; 40  41 void add_edge(int from,int to,int cap) 42 { 43     G[idx].to=to; 44     G[idx].cap=cap; 45     G[idx].next=head[from]; 46     head[from]=idx++; 47      48     G[idx].to=from; 49     G[idx].cap=0; 50     G[idx].next=head[to]; 51     head[to]=idx++; 52 } 53  54 int dfs(int pos,int cost,int cnt) 55 { 56     if(pos==t) 57     { 58         return cost; 59     } 60     int minh=cnt-1; 61     int lv=cost; 62     int d; 63     for(int j=head[pos];j!=-1;j=G[j].next) 64     { 65         int v=G[j].to,cap=G[j].cap; 66         if(cap>0) 67         { 68             if(level[v]+1==level[pos]) 69             { 70                 if(lv<G[j].cap) d=lv; 71                 else d=G[j].cap; 72                  73                 d=dfs(v,d,cnt); 74                 G[j].cap-=d; 75                 G[j^1].cap+=d; 76                 lv-=d; 77                 if(level[s]>=cnt) return cost-lv; 78                 if(lv==0) break; 79             } 80             if(level[v]<minh) minh=level[v]; 81         } 82     } 83     if(lv==cost) 84     { 85         --gap[level[pos]]; 86         if(gap[level[pos]]==0) level[s]=cnt; 87         level[pos]=minh+1; 88         ++gap[level[pos]]; 89     } 90      91     return cost-lv; 92 } 93  94 int sap(int s,int t,int cnt) 95 { 96     int flow=0; 97     gap[s]=cnt; 98     while(level[s]<cnt) 99     {100         flow+=dfs(s,INF,cnt);101     }102     //printf("...%d\n",flow);103     return flow;104 }105 106 void initu(int n)107 {108     for(int i=0;i<=n;i++)109     {110         par[i]=i;111         rankh[i]=0;112     }113 }114 115 int find(int x)116 {117     if(par[x]==x){118         return x;119     }120     else{121         return par[x]=find(par[x]);122     }123 }124 125 void unite(int x,int y)126 {127     x=find(x);128     y=find(y);129     if(x==y) return;130     if(rankh[x]<rankh[y]){131         par[x]=y;132         rankh[y]+=rankh[x];133     }134     else{135         par[y]=x;136 //        rankh[x]++;137         rankh[x]+=rankh[y];138     }139 }140 141 void build(int cap)142 {143     s=0;144     t=2*N+1;145     idx=0;146     memset(gap,0,sizeof(gap));147     memset(level,0,sizeof(level));148     memset(head,-1,sizeof(head));149     memset(judge,0,sizeof(judge));150     for(int i=1;i<=N;i++)151     {152         add_edge(s,i,cap);153         add_edge(N+i,t,cap);154     }155     for(int i=1;i<=M;i++)156     {157         int x=friend1[i].girl;158         int y=friend1[i].boy;159         for(int j=1;j<=N;j++)160         {161             if(par[x]==par[j]&&!judge[j][y]){162                 add_edge(j,N+y,1);163                 judge[j][y]=1;164             }165         }166     }167 }168 169 int main()170 {171     //freopen("/Users/apple/Desktop/暑假/26.1/26.1/in","r",stdin);172     int T;173     scanf("%d",&T);174     while(T--)175     {176         scanf("%d%d%d",&N,&M,&F);177         for(int i=1;i<=M;i++)178             scanf("%d%d",&friend1[i].girl,&friend1[i].boy);179         initu(2*N);180         for(int i=0;i<F;i++)181         {182             int x,y;183             scanf("%d%d",&x,&y);184             unite(x,y);185         }186 //        for(int i=1;i<=2*N;i++)187 //        {188 //            //par[i]=find(i);189 //            printf("%d %d\n",i,par[i]);190 //        }191         for(int i=1;i<=2*N;i++)192         {193             par[i]=find(i);194             //printf("%d %d\n",i,par[i]);195         }196 //        for(int i=1;i<=2*N;i++)197 //        {198 //            //par[i]=find(i);199 //            printf("----%d %d\n",i,par[i]);200 //        }201         int low=0;202         int high=N;203         int res=0;204         while(low<=high)205         {206             int mid=(low+high)/2;207             build(mid);208             if(sap(s,t,t+1)==N*mid)209             {210                 low=mid+1;211                 res=mid;212             }213             else214                 high=mid-1;215         }216         printf("%d\n",res);217     }218     return 0;219 }