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二分图,一些副作用,有几个追求完美搭配(每场比赛没有重复的每一个点的比赛) 后.每次增广一单位,(一次完美匹配) ...
随机推荐
- ssh 远程命令
远程拷贝文件,scp -r 的常用方法: 1.使用该命令的前提条件要求目标主机已经成功安装openssh-server 如没有安装使用 sudo apt-get install openssh-ser ...
- python基础之初识
一. 计算机是什么 基本组成: 主板+cpu+内存 cpu: 主频, 核数(16) 内存:大小(8G, 16G, 32G) 型号: DDR3, DDR4, DDR5, 主频(海盗船,玩家国度) 显卡: ...
- ecshop 漏洞如何修复 补丁升级与安全修复详情
目前ecshop漏洞大面积爆发,包括最新版的ecshop 3.0,ecshop 4.0,ecshop2.7.3全系列版本都存在着高危网站漏洞,导致网站被黑,被篡改,被挂马,许多商城系统深受其漏洞的攻击 ...
- PHP错误:Warning: preg_replace() [function.preg-replace]: Unknown modifier '[' in
遇到一个PHP错误,错误提示是 Warning: preg_replace() [function.preg-replace]: Unknown modifier '[' in .... , 当然了 ...
- VC中编译出现error LNK2005:xx already defined in xxx.obj问题解决。
网上百度说是在.h头文件中定义了全局变量,然后其他文件包括了该头文件的原因. 解决方法如下: 点击项目配置->linker->General->Force file Output设置 ...
- Spring BindingResult验证框架Validation特殊用法
使用注解@Valid(实体属性校验) Springboot实现 Spring实现 一.准备校验时使用的JAR validation-api-1.0.0.GA.jar:JDK的接口: hibernate ...
- Windows Store App下代码加载page resource和resw文件里的string
加载page resource 在page的code behind里: this.Resources["textBoxStyle"] 加载resw文件里的string: Resou ...
- 详解 RPL、DPL、CPL 的关系
保护模式中最重要的一个思想就是通过分级把代码隔离了起来,不同的代码在不同的级别,使大多数情况下都只和同级代码发生关系.Intel的80286以上的cpu可以识別4个特权级(或特权层) ,0级到3级.数 ...
- 创龙TMS320C6748开发板串口和中断学习笔记
1. 硬件上,底板有2个串口,UART1和UART2(使用了MAX3232电平转换芯片),其中UART2也可以转RS485的. 2. 看下数据手册部分,不过一直不理解过采样的意思,16字节的FIFO ...
- 【PHP】进一法取整、四舍五入取整、忽略小数等的取整数方法大全
PHP取整数函数常用的四种方法,下面收集了四个函数:经常用到取整的函数,今天小小的总结一下!其实很简单,就是几个函数而已--主要是:ceil,floor,round,intval PHP取整数函数常用 ...