【HDU3081】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 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<=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 }

[HDU3081]

  所以现在我的数组是能开多大开多大。

2016-05-29 15:09:33

时间: 2024-11-14 12:27:38

【HDU3081】Marriage Match II (二分+最大流)的相关文章

hdu3081 Marriage Match II 二分+最大流

题意: n个男孩n个女孩,女孩选男孩,每个女孩都要选到不同的人 k对女孩有相同选择标准, 女孩每轮都选择没选过的男孩, 问总共能选几轮. 思路: 女孩1..n,男孩n+1..2*n编号 由女孩到男孩建容量为1的边 起点st=2*n+1,到1..n建边: n+1..2*n到终点ed=2*n+2建边 二分搜索最大容量即为答案.详见代码: /********************************************************* file name: hdu3081.cpp

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 &lt;&lt;二分最大流 + 并查集

题意 n个女孩子跟n个男孩子过家家,女孩子选男孩子,告诉你每个女孩子可选的男孩子与女孩子之间的好友关系,好友关系是互相的而且是传递的,然后如果两个女孩子是好友,他们可选的男孩子也是可以合并的.然后每一轮进行匹配,匹配成功后开始下一轮,每个女孩子只能选同一个男孩子一次,问最多能玩几轮. 思路 首先,好友关系的建立显然就直接想到了用并查集处理. 然后在建图时,可以选择是二分图,然后跑完备匹配,每次匹配完后删除匹配边进行下一次匹配. 当然,不会二分图的我就选择直接跑网络流啦,但是建图时候发现需要知道流

HDU-3081 Marriage Match II (最大流,二分答案,并查集)

题目链接:HDU-3081 Marriage Match II 题意 有$n$个男孩和$n$个女孩玩配对游戏,每个女孩有一个可选男孩集合(即每轮游戏的搭档可从集合中选择),已知有些女孩之间是朋友(这里的朋友关系是相互的,即a和b是朋友,a和c是朋友,那么b和c也是朋友),那么她们可以共享男孩集合,即这些男孩集合的并集成为她们各自的可选男孩集合,如果某一轮女孩选择了一个男孩作为搭档,则这个男孩后面不能再作为这个女孩的搭档,问游戏最多进行几轮. 思路 女孩朋友之间共享男孩集合问题可以用并查集解决,将

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

Marriage Match II(二分+并查集+最大流,好题)

Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5420    Accepted Submission(s): 1739 Problem Description Presumably, you all have

hdu3081 Marriage Match II(最大流)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2410    Accepted Submission(s): 820 Problem Description Presumably, y

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",

HDU3081 Marriage Match II 【最大匹配】

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2296    Accepted Submission(s): 786 Problem Description Presumably, you all have known the question of stable marriage match. A

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

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