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. The Road to learn React书籍学习笔记(第四章)

    高级React组件 本章将重点介绍高级 React 组件的实现.我们将了解什么是高阶组件以及如何实现它们.此外,我们还将深入探讨 React 中更高级的主题,并用它实现复杂的交互功能. 引用 DOM ...

  2. kafka单机部署文档

    单机Kafka部署文档 最简单的使用方式,单机,使用自带的zookeeper 1.解压 下载地址:http://pan.baidu.com/s/1i4K2pXr tar –zxvf kafka_2.1 ...

  3. windows下subversion服务器搭建

    一.下载subversion服务器端和客户端软件 1.subversion下载地址:http://subversion.tigris.org/ 2.svn比较流行的客户端Tortoisesvn下载地址 ...

  4. 20145202马超《网络对抗》Exp3免杀 进阶

    木马化正常软件,如通过改变机器指令.实现可免杀免防火墙提示的后门. 继上次实验3所做的代码在主函数里面加上一行调用就可以 改各种属性,这里我参考了郝浩同学的博客 最后我还是遇到了问题 后来发现虽然有那 ...

  5. 【转】使用git提交项目到码云

    一.git安装 1.首先在官方网站下载git工具,或者根据以下链接进行下载:http://download.csdn.net/detail/qq_27501889/9788879(此链接版本为git- ...

  6. 1698-Just a Hook 线段树(区间替换)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. 深入浅出 Webpack

    深入浅出 Webpack 评价 Webpack 凭借强大的功能与良好的使用体验,已经成为目前最流行,社区最活跃的打包工具,是现代 Web 开发必须掌握的技能之一.作者结合自身的实战经验,介绍了 Web ...

  8. 失败的尝试,使用继承扩展数组,以及ES6的必要性

    我们都知道直接在原生对象上扩展对象是很不好的.所以prototype这样的库广受非议. 一些库,比如lodash采用了工具包形式的扩展方式,绕开了对象的继承. 由于es6的class的出现,我尝试以A ...

  9. SQL 注入教程

    SQL 注入测评教程 1     准备 安装包:Burpsuit.Python27.sqlmap 2     安装配置 2.1    Burpsuit 1)       解压Burpsuit 2)   ...

  10. python 基础篇 15 内置函数和匿名函数

    ------------------------>>>>>>>>>>>>>>>内置函数<<< ...