首页 > 代码库 > HDU 3277 Marriage Match III

HDU 3277 Marriage Match III

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

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

HDU 3081 Marriage Match II  

不同的是,女生交换朋友的时候也不能和争吵过得男生组成家庭。

问能交换多少次。

题解:与3081那道题主要不同的地方是多了拆点。

   建边:将女生拆点为女生1,女生2。源点和女生1建边,边权依旧是mid;男生和汇点建边,边权是mid;女生1和女生2建边,边权是K;如果女生和男生可以组成家庭,女生1和男生建       边,边权为1,否则女生2和男生建边,边权为2。

T了很多发……优化了并查集的判断。抄了别人的ISAP的板子http://www.350351.com/bianchengyuyan/Cyuyan/318117.html

  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 const int maxm=10000010; 23 const int maxn=260; 24  25 struct edge{ 26     int u,v,cap,next; 27 }G[maxm]; 28 struct node{ 29     int girl,boy; 30 }friend1[maxm]; 31 int judge[maxn][maxn]; 32 int idx; 33 int head[maxn*maxn],level[maxn*maxn]; 34 int num[maxn*maxn]; 35 int cur[maxn*maxn]; 36 int pre[maxn*maxn]; 37 int s,t,tt; 38 int par[maxn*maxn]; 39 int rankh[maxn*maxn]; 40 int N,M,K,F; 41  42 void init(int n) 43 { 44     for(int i=0;i<=n;i++) 45     { 46         par[i]=i; 47     } 48 } 49  50 int find(int x) 51 { 52     if(par[x]==x){ 53         return x; 54     }else{ 55         return par[x]=find(par[x]); 56     } 57 } 58  59 void unite(int x,int y) 60 { 61     x=find(x); 62     y=find(y); 63     if(x==y) return; 64     else{ 65         par[x]=y; 66     } 67 } 68  69 void build(int u,int v,int cap) 70 { 71     G[idx].v=v; 72     G[idx].cap=cap; 73     G[idx].next=head[u]; 74     head[u]=idx++; 75 } 76  77 void add_edge(int u,int v,int cap) 78 { 79     build(u,v,cap); 80     build(v,u,0); 81 } 82  83  84 void bfs() 85 { 86     memset(level,-1,sizeof(level)); 87     memset(num,0,sizeof(num)); 88     queue<int>q; 89     q.push(t); 90     level[t]=0; 91     num[0]=1; 92     while(!q.empty()) 93     { 94         int u=q.front(); 95         q.pop(); 96         for(int i=head[u];i!=-1;i=G[i].next) 97         { 98             int v=G[i].v; 99             if(level[v]==-1)100             {101                 level[v]=level[u]+1;102                 num[level[v]]++;103                 q.push(v);104             }105         }106     }107 }108 109 int ISAP()110 {111     memcpy(cur,head,sizeof(cur));112     bfs();113     int flow=0;114     int u=pre[s]=s;115     while(level[s]<tt)116     {117         if(u==t){118             int f=INF,pos;119             for(int i=s;i!=t;i=G[cur[i]].v)120             {121                 if(f>G[cur[i]].cap){122                     f=G[cur[i]].cap;123                     pos=i;124                 }125             }126             for(int i=s;i!=t;i=G[cur[i]].v)127             {128                 G[cur[i]].cap-=f;129                 G[cur[i]^1].cap+=f;130             }131             flow+=f;132             u=pos;133         }134         int i;135         for(i=cur[u];i!=-1;i=G[i].next)136         {137             if(level[G[i].v]+1==level[u]&&G[i].cap) break;138         }139         if(i!=-1){140             cur[u]=i;141             pre[G[i].v]=u;142             u=G[i].v;143         }144         else{145             if(--num[level[u]]==0) break;146             int mind=tt;147             for(int i=head[u];i!=-1;i=G[i].next)148             {149                 if(mind>level[G[i].v]&&G[i].cap){150                     mind=level[G[i].v];151                     cur[u]=i;152                 }153             }154             level[u]=mind+1;155             num[level[u]]++;156             u=pre[u];157         }158     }159     return flow;160 }161 162 void build_graph(int cap)163 {164     memset(head,-1,sizeof(head));165     idx=0;166     for(int i=1;i<=N;i++)167     {168         for(int j=1;j<=N;j++)169         {170             if(judge[find(i)][j]){171                 add_edge(i,2*N+j,1);172             }173             else{174                 add_edge(N+i,2*N+j,1);175             }176         }177     }178     for(int i=1;i<=N;i++)179     {180         add_edge(s,i,cap);//源点-女生(1~N)181         add_edge(2*N+i,t,cap);//男生-汇点(2*N+1~3*N)182         add_edge(i,N+i,K);//女生1-女生2183     }184 }185 186 int main()187 {188    // freopen("/Users/apple/Desktop/暑假/27(2)/27(2)/in","r",stdin);189     int T;190     scanf("%d",&T);191     while(T--)192     {193         scanf("%d%d%d%d",&N,&M,&K,&F);194         s=0;195         t=3*N+1;196         tt=t+1;197         memset(judge,0,sizeof(judge));198         199         for(int i=0;i<M;i++)200             scanf("%d%d",&friend1[i].girl,&friend1[i].boy);201         202         init(3*N);203         204         for(int i=0;i<F;i++)205         {206             int g1,g2;207             scanf("%d%d",&g1,&g2);208             unite(g1,g2);209         }210         for(int i=0;i<M;i++)211         {212             int x=friend1[i].girl,y=friend1[i].boy;213             judge[find(x)][y]=1;214         }215         216         int low=0;217         int high=N;218         int res=0;219         while(low<=high)220         {221             int mid=(low+high)/2;222             build_graph(mid);223             if(ISAP()>=N*mid) {224                 res=mid;225                 low=mid+1;226             }227             else{228                 high=mid-1;229             }230         }231         printf("%d\n",res);232     }233     234     return 0;235 }