HDU 3081 Marriage Match II(网络流+并查集+二分答案)

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

题目:

Problem Description

Presumably, 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 3

Sample Output

2

题意:n个男生和n个女生选伴侣。(女士优先)女生选择和自己没有吵过架的男生或者选择和自己朋友没有吵过架的男生。问最多有多少种选择方案能使得这n个女生和n个男生全部匹配完成。

题解:首先,先并查集把女生们分为若干个集合,每个的集合里面能匹配的男生都是共享的,标记一下。然后二分答案,构图:创建一个超级源点,把超级源点和每个女生连接,容量为mid;

每个女生和能匹配的男生都连接起来,容量为1;创建一个超级汇点,把每个男生和超级汇点连接,容量为mid。最后跑下网络流,判断下最大流量是否等于n*mid。

  1 //HDU 3081
  2 #include <queue>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <algorithm>
  7 using namespace std;
  8
  9 const int N=2333;
 10 const int M=233333;
 11 const int INF=0x3f3f3f3f;
 12 int n,m,f,s,t,cnt;
 13 int Head[N],Depth[N],cur[N],Father[N];
 14 int Next[M],V[M],W[M];
 15 bool Map[N][N];
 16
 17 int Find(int x){return x==Father[x]?x:Father[x]=Find(Father[x]);}
 18 void Union(int x,int y){
 19     int fx=Find(x),fy=Find(y);
 20     if(fx!=fy){
 21         Father[fx]=fy;
 22     }
 23 }
 24
 25 void init(){
 26     cnt=-1;
 27     memset(Head,-1,sizeof(Head));
 28     memset(Next,-1,sizeof(Next));
 29 }
 30
 31 void add_edge(int u,int v,int w){
 32     cnt++;Next[cnt]=Head[u];V[cnt]=v;W[cnt]=w;Head[u]=cnt;
 33     cnt++;Next[cnt]=Head[v];V[cnt]=u;W[cnt]=0;Head[v]=cnt;
 34 }
 35
 36 bool bfs(){
 37     queue <int> Q;
 38     while(!Q.empty()) Q.pop();
 39     memset(Depth,0,sizeof(Depth));
 40     Depth[s]=1;
 41     Q.push(s);
 42     while(!Q.empty()){
 43         int u=Q.front();Q.pop();
 44         for(int i=Head[u];i!=-1;i=Next[i]){
 45             if((W[i]>0)&&(Depth[V[i]]==0)){
 46                 Depth[V[i]]=Depth[u]+1;
 47                 Q.push(V[i]);
 48             }
 49         }
 50     }
 51     if(Depth[t]==0) return 0;
 52     return 1;
 53 }
 54
 55 int dfs(int u,int dist){
 56     if(u==t) return dist;
 57     for(int& i=cur[u];i!=-1;i=Next[i]){
 58         if((Depth[V[i]]==Depth[u]+1)&&W[i]!=0){
 59             int di=dfs(V[i],min(dist,W[i]));
 60             if(di>0){
 61                 W[i]-=di;
 62                 W[i^1]+=di;
 63                 return di;
 64             }
 65         }
 66     }
 67     return 0;
 68 }
 69
 70 int Dinic(){
 71     int ans=0;
 72     while(bfs()){
 73         for(int i=0;i<=2*n+1;i++) cur[i]=Head[i];
 74         while(int d=dfs(s,INF)) ans+=d;
 75     }
 76     return ans;
 77 }
 78
 79 int check(int k){
 80     init();
 81     for(int i=1;i<=n;i++)
 82     for(int j=1+n;j<=2*n;j++)
 83     if(Map[i][j]) add_edge(i,j,1);
 84
 85     for(int i=1;i<=n;i++) add_edge(s,i,k);
 86     for(int i=1+n;i<=2*n;i++) add_edge(i,t,k);
 87
 88     if(Dinic()==k*n) return 1;
 89     else return 0;
 90 }
 91
 92 int main(){
 93     int T,a,b;
 94     scanf("%d",&T);
 95     while(T--){
 96         memset(Map,0,sizeof(Map));
 97         for(int i=0;i<N;i++) Father[i]=i;
 98         scanf("%d %d %d",&n,&m,&f);
 99         for(int i=1;i<=m;i++){
100             scanf("%d %d",&a,&b);
101             Map[a][b+n]=1;
102         }
103         for(int i=1;i<=f;i++){
104             scanf("%d %d",&a,&b);
105             Union(a,b);
106         }
107         for(int i=1;i<=n;i++)
108         for(int j=i+1;j<=n;j++)
109             if(Find(i)==Find(j)){
110                 for(int k=1+n;k<=2*n;k++){
111                     Map[i][k]=Map[j][k]=(Map[i][k]||Map[j][k]);
112                 }
113             }
114         int s=0;t=2*n+1;
115         int l=0,r=111,mid;
116         while(r-l>1){
117             mid=(l+r)/2;
118             if(check(mid)) l=mid;
119             else r=mid;
120         }
121         printf("%d\n",l);
122     }
123     return 0;
124 }

//还有一种匈牙利的方法(二分图最大匹配),如果跑完完全匹配,答案+1,拆掉这种方案的所有边,然后接着跑,直到没有能完全匹配。

时间: 2024-12-05 16:27:02

HDU 3081 Marriage Match II(网络流+并查集+二分答案)的相关文章

HDU 3081 Marriage Match II【并查集+二分图最大匹配】

大意:有n个男孩n个女孩,告诉你每个女孩喜欢哪些男孩,又告诉你女孩之间的存在一些朋友关系 一个女孩可以和她喜欢的男孩结婚也可以和她朋友喜欢的男孩结婚, 并且朋友关系可以传递 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 boyfr

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

hdu 3081 Marriage Match II Description Presumably, 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 p

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

Marriage Match II                                                                           Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Presumably, you all have known the question of stable

HDU 3081 Marriage Match II(二分法+最大流量)

HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个女孩n个男孩,每一个女孩能够和一些男孩配对.然后有些女孩是朋友.满足这个朋友圈里面的人,假设有一个能和某个男孩配对,其它就都能够,然后每轮要求每一个女孩匹配到一个男孩.且每轮匹配到的都不同,问最多能匹配几轮 思路:二分轮数k,然后建图为,源点连向女孩,男孩连向汇点容量都为k,然后女孩和男孩之间连边为.有关系的

HDU 3081 Marriage Match II(二分+最大流)

HDU 3081 Marriage Match II 题目链接 题意:n个女孩n个男孩,每个女孩可以和一些男孩配对,然后有些女孩是朋友,满足这个朋友圈里面的人,如果有一个能和某个男孩配对,其他就都可以,然后每轮要求每个女孩匹配到一个男孩,且每轮匹配到的都不同,问最多能匹配几轮 思路:二分轮数k,然后建图为,源点连向女孩,男孩连向汇点容量都为k,然后女孩和男孩之间连边为,有关系的连边容量1,这样一个匹配对应一条边,且不会重复,每次判断最大流是否等于n * k即可 代码: #include <cst

HDU 3081 Marriage Match II 二分+最大流

题目来源:HDU 3081 Marriage Match II 题意: 思路: 错误代码 纠结不知道哪错了 先放一放 #include <cstdio> #include <queue> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1010; const int INF = 999999999; st

HDU 3081 Marriage Match II 二分 + 网络流

Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女生配对,每轮配对过的人在接下来中都不能配对,求这个k最大是多少. 题解:二分 + 网络流check . 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt",

HDU 3081 Marriage Match II

Marriage Match II Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 308164-bit integer IO format: %I64d      Java class name: Main Presumably, you all have known the question of stable marriage match. A girl wi

HDU 3081 Marriage Match II 二分图最大匹配

Marriage Match II Problem Description Presumably, 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 pl