HDU3081Marriage Match II (二分+最大流)
Posted konjak魔芋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3081Marriage Match II (二分+最大流)相关的知识,希望对你有一定的参考价值。
DescriptionPresumably, you all have known the question of stable marriage match. A girl will choose a boy; it is similar as the game of playing house we used to play when we are kids. What a happy time as so many friends playing together. And it is normal that a fight or a quarrel breaks out, but we will still play together after that, because we are kids.
Now, there are 2n kids, n boys numbered from 1 to n, and n girls numbered from 1 to n. you know, ladies first. So, every girl can choose a boy first, with whom she has not quarreled, to make up a family. Besides, the girl X can also choose boy Z to be her boyfriend when her friend, girl Y has not quarreled with him. Furthermore, the friendship is mutual, which means a and c are friends provided that a and b are friends and b and c are friend.
Once every girl finds their boyfriends they will start a new round of this game—marriage match. At the end of each round, every girl will start to find a new boyfriend, who she has not chosen before. So the game goes on and on.
Now, here is the question for you, how many rounds can these 2n kids totally play this game?Input
There are several test cases. First is a integer T, means the number of test cases.
Each test case starts with three integer n, m and f in a line (3<=n<=100,0<m<n*n,0<=f<n). n means there are 2*n children, n girls(number from 1 to n) and n boys(number from 1 to n).
Then m lines follow. Each line contains two numbers a and b, means girl a and boy b had never quarreled with each other.
Then f lines follow. Each line contains two numbers c and d, means girl c and girl d are good friends.Output
For each case, output a number in one line. The maximal number of Marriage Match the children can play.Sample Input
1 4 5 2 1 1 2 3 3 2 4 2 4 4 1 4 2 3Sample Output
2
n个女生与n个男生配对,每个女生只能配对某些男生,有些女生相互是朋友,每个女生也可以跟她朋友能配对的男生配对。
每次配对,每个女生都要跟不同的男生配对且每个女生都能配到对。问最多能配对几轮。(n<=100)
【分析】
二分答案,因为有单调性。然后直接最大流了。输入那里要用并查集。
注意不能直接跑最大流哦,(因为你不知道跑完最大流之后ans是啥啊)
哇塞~TLE了一辈子,dinic中几个不起眼的优化也能是可以挽救你于水火之中啊。比如下面的加粗部分:
int find_flow(int x,int flow)
{
if(x==ed) return flow;
int now=0;
for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
{
int y=t[i].y;
if(dis[y]==dis[x]+1)
{
int a=find_flow(y,mymin(t[i].f,flow-now));
t[i].f-=a;
t[t[i].o].f+=a;
now+=a;
if(now==flow) break;
}
}
if(now==0) dis[x]=-1;
return now;
}
我这个傻逼还因为数组开小了TLE了好一阵子。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 #define Maxn 210 9 #define Maxm 10010 10 #define INF 0xfffffff 11 12 int fa[Maxn],first[Maxn],dis[Maxn]; 13 bool map[Maxn][Maxn]; 14 15 struct node 16 { 17 int x,y,f,o,next; 18 }; 19 node t[10*Maxm],tt[10*Maxm];int len; 20 21 int st,ed; 22 int n,m,k; 23 24 int mymin(int x,int y) {return x<y?x:y;} 25 26 void ins(int x,int y,int f) 27 { 28 tt[++len].x=x;tt[len].y=y;tt[len].f=f; 29 tt[len].next=first[x];first[x]=len;tt[len].o=len+1; 30 tt[++len].x=y;tt[len].y=x;tt[len].f=0; 31 tt[len].next=first[y];first[y]=len;tt[len].o=len-1; 32 } 33 34 int ffind(int x) 35 { 36 if(fa[x]!=x) fa[x]=ffind(fa[x]); 37 return fa[x]; 38 } 39 40 queue<int > q; 41 bool bfs() 42 { 43 while(!q.empty()) q.pop(); 44 memset(dis,-1,sizeof(dis)); 45 q.push(st);dis[st]=0; 46 while(!q.empty()) 47 { 48 int x=q.front();q.pop(); 49 for(int i=first[x];i;i=t[i].next) if(t[i].f>0) 50 { 51 int y=t[i].y; 52 if(dis[y]==-1) 53 { 54 dis[y]=dis[x]+1; 55 q.push(y); 56 } 57 } 58 } 59 if(dis[ed]==-1) return 0; 60 return 1; 61 } 62 63 int find_flow(int x,int flow) 64 { 65 if(x==ed) return flow; 66 int now=0; 67 for(int i=first[x];i;i=t[i].next) if(t[i].f>0) 68 { 69 int y=t[i].y; 70 if(dis[y]==dis[x]+1) 71 { 72 int a=find_flow(y,mymin(t[i].f,flow-now)); 73 t[i].f-=a; 74 t[t[i].o].f+=a; 75 now+=a; 76 if(now==flow) break; 77 } 78 } 79 if(now==0) dis[x]=-1; 80 return now; 81 } 82 83 int max_flow() 84 { 85 int ans=0; 86 while(bfs()) 87 ans+=find_flow(st,INF); 88 return ans; 89 } 90 91 bool check(int x) 92 { 93 for(int i=1;i<=len;i++) t[i]=tt[i]; 94 for(int i=len-4*n+1;i<=len;i+=2) t[i].f=x; 95 return max_flow()==n*x; 96 } 97 98 void finda() 99 { 100 int l=0,r=n*n; 101 while(l<r) 102 { 103 int mid=(l+r+1)>>1; 104 if(check(mid)) l=mid; 105 else r=mid-1; 106 } 107 printf("%d\\n",l); 108 } 109 110 int main() 111 { 112 int T; 113 scanf("%d",&T); 114 while(T--) 115 { 116 len=0; 117 memset(first,0,sizeof(first)); 118 memset(map,0,sizeof(map)); 119 scanf("%d%d%d",&n,&m,&k); 120 for(int i=1;i<=m;i++) 121 { 122 int x,y; 123 scanf("%d%d",&x,&y); 124 map[x][y]=1; 125 } 126 for(int i=1;i<=n;i++) fa[i]=i; 127 for(int i=1;i<=k;i++) 128 { 129 int x,y; 130 scanf("%d%d",&x,&y); 131 fa[ffind(x)]=ffind(y); 132 } 133 for(int i=1;i<=n;i++) 134 for(int j=1;j<=n;j++) if(ffind(i)==ffind(j)) 135 { 136 for(int k=1;k<=n;k++) if(map[j][k]) 137 map[i][k]=1; 138 } 139 for(int i=1;i<=n;i++) 140 for(int j=1;j<=n;j++) if(map[i][j]) 141 ins(i,j+n,1); 142 st=2*n+1;ed=st+1; 143 for(int i=1;i<=n;i++) ins(st,i,INF); 144 for(int i=1;i<=n;i++) ins(i+n,ed,INF); 145 finda(); 146 } 147 return 0; 148 }
所以现在我的数组是能开多大开多大。
2016-05-29 15:09:33
以上是关于HDU3081Marriage Match II (二分+最大流)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3081 Marriage Match II(网络流+并查集+二分答案)
HDU 3081 Marriage Match II 二分 + 网络流
HDU-3081 Marriage Match II (最大流,二分答案,并查集)
HDU 3081:Marriage Match II(二分图匹配+并查集)