HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))
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:
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/并查集+二分图匹配/最大流(+二分))的更多相关文章
- HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流
题目链接:https://vjudge.net/problem/HDU-3081 Marriage Match II Time Limit: 2000/1000 MS (Java/Others) ...
- hdu3081 Marriage Match II(最大流)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Marriage Match II Time Limit: 2000/1000 M ...
- hdu3081 Marriage Match II(二分+并查集+最大流)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意: n个女生与n个男生配对,每个女生只能配对某些男生,有些女生相互是朋友,每个女生也可以跟她 ...
- BZOJ 1854: [Scoi2010]游戏 [连通分量 | 并查集 | 二分图匹配]
题意: 有$n \le 10^6$中物品,每种两个权值$\le 10^4$只能选一个,使得选出的所有权值从1递增,最大递增到多少 一开始想了一个奇怪的规定流量网络流+二分答案做法...然而我还不知道怎 ...
- hdu3081 Marriage Match II
新年第一篇,又花了一早上,真是蠢啊! 二分+网络流 之前对于讨论哪些人是朋友的时候复杂度过高 直接n3的暴力虽然看起来复杂度高,其实并不是每次都成立 #include<bits/stdc++.h ...
- HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)
HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...
- HDU 3081 Marriage Match II (二分图,并查集)
HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...
- Marriage Match II(二分+并查集+最大流,好题)
Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Othe ...
- hdu 3081 hdu 3277 hdu 3416 Marriage Match II III IV //灵活运用最大流量
3081 意甲冠军: n女生选择不吵架,他甚至男孩边(他的朋友也算.并为您收集过程).2二分图,一些副作用,有几个追求完美搭配(每场比赛没有重复的每一个点的比赛) 后.每次增广一单位,(一次完美匹配) ...
随机推荐
- 前端学习之HTML基础
要点: 理解HTTP请求响应模式及通信规范 HTML的各种标签和常用标签 CSS是用于样式渲染和定位布局 JS将HTML动态化 jquery是JS的高级封装 理解HTTP请求响应模式及通信规范 HTT ...
- 谭浩强C语言第四版第九章课后习题7--9题(建立,输出,删除,插入链表处理)
#include<stdio.h> #include<stdlib.h> #define N sizeof(link) typedef struct stu { struct ...
- PAT-A1002
1002 A+B for Polynomials (25) Polynomials多项式,exponents指数,coefficients系数 输入:两行数据,每行表示一个多项式:第一个数字表示非零项 ...
- class实现Stack
基于class实现一个存储string类型的Stack 头文件: //stack.h #include<vector> #include<string> class Stack ...
- stm32+lwip(二):UDP测试
我是卓波,很高兴你来看我的博客. 系列文章: stm32+lwip(一):使用STM32CubeMX生成项目 stm32+lwip(二):UDP测试 stm32+lwip(三):TCP测试 stm32 ...
- go学习笔记-常见命令
常见命令 go 命令 可以在控制台执行go来查看 go Go is a tool for managing Go source code. Usage: go <command> [arg ...
- R语言学习笔记(十六):构建分割点函数
选取预测概率的分割点 cutoff<- function(n,p){ pp<-1 i<-0 while (pp>=0.02) { model.predfu<-rep(&q ...
- 【转】Git远程操作详解
Git是目前最流行的版本管理系统,学会Git几乎成了开发者的必备技能. Git有很多优势,其中之一就是远程操作非常简便.本文详细介绍5个Git命令,它们的概念和用法,理解了这些内容,你就会完全掌握Gi ...
- Code First Migrations更新数据库结构(数据迁移) 【转】
注意:一旦正常后,每次数据库有变化,做如下两步: 1. Enable-Migrations 2.update-database 背景 code first起初当修改model后,要持久化至数据库中时, ...
- mysql ON DUPLICATE KEY UPDATE、REPLACE INTO
INSERT INTO ON DUPLICATE KEY UPDATE 与 REPLACE INTO,两个命令可以处理重复键值问题,在实际上它之间有什么区别呢?前提条件是这个表必须有一个唯一索引或主键 ...