Marriage Match II

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5469    Accepted Submission(s): 1756

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

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个男生,每个女生都有一个选择男生的集合。其中有些女生是朋友关系,朋友之间可以选择彼此男生的集合 /斜眼笑。

现在进行游戏,每个女生都选择一名之前没有选择过的男生,当所有男女成功配对后就分手然后开始下一轮游戏= =

这里都是女生选择男生,问最多能成功进行几轮游戏。

题解:

先说说用网络流的解法。

首先用并查集或者floyd算法解决朋友之间的问题(女生可以选择其朋友的男生集合)。

然后考虑女生向其能够选择的男生连容量为1 的边,源点向女生连容量为1的边,男生向汇点连容量为1的边。

之后不断地跑网络流然后删边就行了。

但是这样做有点麻烦。我们会发现,每次删边后流从其他边走,等价于在这个点的入流和出流可以为2。

然后就可以这样想:二分回合数,与源点和汇点相连的边的容量为二分值,然后直接跑最大流就行了。

如果max_flow=n*mid,说明回合数可以调大点,否则就调小点。

下面是用并查集的网络流:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <set>
#define INF 1e9
#define t 300
using namespace std;
typedef long long ll;
const int N = ;
int T,cnt;
int n,m,F,tot;
int head[N],f[N],map[N],d[N];
vector <int > g[N];
vector <int > vec[N];
set <int > S[N];
struct Edge{
int v,next,c;
}e[(N*N)<<];
void adde(int u,int v,int c){
e[tot].v=v;e[tot].next=head[u];e[tot].c=c;head[u]=tot++;
e[tot].v=u;e[tot].c=;e[tot].next=head[v];head[v]=tot++;
}
int find(int x){
return f[x]==x ? f[x] : f[x]=find(f[x]);
}
int bfs(){
memset(d,,sizeof(d));d[]=;
queue <int > q;q.push();
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i!=-;i=e[i].next){
int v=e[i].v;
if(e[i].c> && !d[v]){
d[v]=d[u]+;
q.push(v);
}
}
}
return d[t]!=;
}
int dfs(int s,int a){
if(s==t || a==) return a;
int flow=,f;
for(int i=head[s];i!=-;i=e[i].next){
int v=e[i].v;
if(d[v]!=d[s]+) continue ;
f=dfs(v,min(a,e[i].c));
if(f>){
e[i].c-=f;
e[i^].c+=f;
flow+=f;
a-=f;
if(a==) break;
}
}
if(!flow) d[s]=-;
return flow;
}
int Dinic(){
int flow=;
while(bfs())
flow+=dfs(,INF);
return flow;
}
int check(int mid){
memset(head,-,sizeof(head));tot=;
for(int i=;i<=cnt;i++) for(auto v:vec[i]) for(auto k:S[i]) adde(v,n+k,);
for(int i=;i<=n;i++) adde(,i,mid);
for(int i=n+;i<=n+n;i++) adde(i,t,mid);
int max_flow=Dinic();
if(max_flow==mid*n) return ;
return ;
}
int main(){
scanf("%d",&T);
while(T--){
memset(g,,sizeof(g));memset(map,,sizeof(map));
scanf("%d%d%d",&n,&m,&F);
for(int i=;i<=t;i++) f[i]=i,g[i].clear(),vec[i].clear(),S[i].clear();
for(int i=,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
g[u].push_back(v);
}
for(int i=,x,y;i<=F;i++){
scanf("%d%d",&x,&y);
int fx=find(x),fy=find(y);
if(fx!=fy) f[fx]=fy;
}
cnt= ;
for(int i=;i<=n;i++){
int fx=find(i);
if(fx==i){
vec[++cnt].push_back(i);
map[fx]=cnt;
}
}
for(int i=;i<=n;i++)
if(f[i]!=i) vec[map[f[i]]].push_back(i);
for(int i=;i<=cnt;i++){
for(auto v:vec[i]){
for(auto tmp:g[v]) S[i].insert(tmp);
}
}
int l=,r=n+;
while(l<r){
int mid=(l+r)>>;
if(check(mid)) l=mid+;
else r=mid;
}
printf("%d\n",l-);
}
return ;
}

之后再说说二分图匹配。

其实二分图匹配就是我们之前分析的第一种思想,每次就不断地拆边就行了...

下面是用floyd传递闭包的二分图匹配:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int N = ;
int check[N],match[N];
int n,m,f,T;
int g[N][N];
int dfs(int s){
for(int i=n+;i<=*n;i++){
if(!g[s][i] || check[i]) continue ;
check[i]=;
if(match[i]==- || dfs(match[i])){
match[i]=s;
return ;
}
}
return ;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&f);
memset(g,,sizeof(g));
for(int i=;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u][v+n]=;
}
for(int i=;i<=f;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u][v]=g[v][u]=;
}
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=*n;j++)
g[i][j]=(g[i][k]&&g[k][j])||g[i][j];
int ans = ,flag=;
while(){
flag = ;
memset(match,-,sizeof(match));
for(int i=;i<=n;i++){
memset(check,,sizeof(check));
if(!dfs(i)){
flag=;
break ;
}
}
if(flag) break;
for(int i=n+;i<=*n;i++)
g[match[i]][i]=;
ans++;
}
printf("%d\n",ans);
}
return ;
}

HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))的更多相关文章

  1. HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流

    题目链接:https://vjudge.net/problem/HDU-3081 Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    ...

  2. hdu3081 Marriage Match II(最大流)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Marriage Match II Time Limit: 2000/1000 M ...

  3. hdu3081 Marriage Match II(二分+并查集+最大流)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意: n个女生与n个男生配对,每个女生只能配对某些男生,有些女生相互是朋友,每个女生也可以跟她 ...

  4. BZOJ 1854: [Scoi2010]游戏 [连通分量 | 并查集 | 二分图匹配]

    题意: 有$n \le 10^6$中物品,每种两个权值$\le 10^4$只能选一个,使得选出的所有权值从1递增,最大递增到多少 一开始想了一个奇怪的规定流量网络流+二分答案做法...然而我还不知道怎 ...

  5. hdu3081 Marriage Match II

    新年第一篇,又花了一早上,真是蠢啊! 二分+网络流 之前对于讨论哪些人是朋友的时候复杂度过高 直接n3的暴力虽然看起来复杂度高,其实并不是每次都成立 #include<bits/stdc++.h ...

  6. HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)

    HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...

  7. HDU 3081 Marriage Match II (二分图,并查集)

    HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...

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

    Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Othe ...

  9. hdu 3081 hdu 3277 hdu 3416 Marriage Match II III IV //灵活运用最大流量

    3081 意甲冠军: n女生选择不吵架,他甚至男孩边(他的朋友也算.并为您收集过程).2二分图,一些副作用,有几个追求完美搭配(每场比赛没有重复的每一个点的比赛) 后.每次增广一单位,(一次完美匹配) ...

随机推荐

  1. Kuernetes-设计架构(二)

    Kubernetes设计架构 Kubernetes集群包含有节点代理kubelet和Master组件(APIs,scheduler.etc),一切都基于分布式的存储系统.Kubernetes架构图: ...

  2. Lucene如何实现多条件搜索?

    有两种方式可以实现, 一是:Lucene搜索API中提供了一个布尔查询器(BooleanQuery),它可以包含多个查询器,每个查询器Occur枚举控制是“and” 还是“or” BooleanQue ...

  3. .Net 面试题 汇总(二)

    51..net中读写XML的类都归属于哪些命名空间? 答:System.Xml 52.解释一下UDDI.WSDL的意义及其作用. 答:UDDI即统一描述.发现和集成协议.作用: 用来说明一个Web服务 ...

  4. ProxySQL读写分离测试(续)

      Preface       I've implemented ProxySQL on PXC yesterday but got some errors when configured query ...

  5. 「暑期训练」「Brute Force」 Optimal Point on a Line (Educational Codeforces Round 16, B)

    题意 You are given n points on a line with their coordinates $x_i$. Find the point x so the sum of dis ...

  6. 初探Qt Opengl【1】

    最近一直在学习Qt的opengl绘图,看到好多资源都是关于以前的旧版本的, 我将我这几天学的的部分关于opengl的做个总结,也希望对需要学习的人有一定的帮助 在我的学习中,我主要用到一下三个方法 # ...

  7. 常用模块(数据序列化 json、pickle、shelve)

    本节内容 前言 json模块 pickle模块 shelve模块 总结 一.前言 1. 现实需求 每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),Py ...

  8. Ajax请求被缓存的几种处理方式

    Ajax请求被缓存的几种处理方式 我们都知道IE会针对ajax请求的地址缓存请求结果,直到缓存过期之前,针对相同地址发出的请求,只有第一次会请求会真正发送到服务端.在某种情况下,这种缓存机制确实能提高 ...

  9. resetroot_169route_python3(用于ubuntu16.04)

    #!/usr/bin/python3 import os import sys import json import urllib.request import urllib.parse import ...

  10. Visual Studio Code 配置Go 开发环境最简单的方法!!!

    由于大家都知道的原因,在国内如果想访问go等各种资源,都会遇到某种不可预知的神奇问题.导致在VS Code中安装 go 各种插件都会失败. 于是乎,网上就出现了各种各样的解决方案:什么手动git cl ...