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

题意:

n个女生与n个男生配对,每个女生只能配对某些男生,有些女生相互是朋友,每个女生也可以跟她朋友能配对的男生配对。

每次配对,每个女生都要跟不同的男生配对且每个女生都能配到对。问最多能配对几轮。

思路:

这道题乍看之下好像是二分匹配,但仔细一想是不太一样的。考虑用网络流做,首先女生可以与她朋友能配对的男生配对,这样需要用并查集保存他们可以配对的关系,这一点应该不难想到。接下来就是建图了,每个女生与可以配对的男生(包括朋友的可配对的男生)之间建边,容量为 1。 这样需要考虑的就是源点和女生、男生和汇点之间该如何建边了。

本来考虑到n个女生和n个男生不重复完全配对最多只能进行n轮,想到可以将源点和女生、男生和汇点之间的容量赋为n,求出最大流。但是发现这样是不行的,如果有女生或者男生无法配对到,即一轮都无法进行,这样得到的答案就不对了。为了保证每一轮所有女生和男生都能匹配到,我们需要二分源点和女生、男生和汇点之间的容量k,并且需要保证满流。找到最大的满足条件的k就是答案。

解法的正确性可以用数学归纳法证明,简单来说,当k=1时,转化为一个二分匹配,如果满流,就说明可以进行一轮。当k-1轮可以实现时(k-1满流),如果容量为k时满流,说明也可以实现k轮。这样就证明了正确性。

由这个解法我们也可以想到用二分匹配的方法来解决:进行二分图的最大匹配,在匹配完成后判断匹配数是否等于n,不是的话说明GAME OVER 求得答案,是的话说明游戏能完成,然后进行删边操作,再继续匹配,直到匹配数<n为止。

下面给出二分最大流的代码:

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring> using namespace std;
const int MAXN = ;
const int MAXM = ;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to, next, cap, flow;
}edge[MAXM];
int tol;
int head[MAXN];
void init()
{
tol = ;
memset(head, -, sizeof(head));
}
void addedge(int u, int v, int w, int rw=)
{
edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = ;
edge[tol].next = head[u]; head[u] = tol++;
edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = ;
edge[tol].next = head[v]; head[v] = tol++;
}
int Q[MAXN];
int dep[MAXN], cur[MAXN], sta[MAXN];
bool bfs(int s, int t, int n)
{
int front = , tail = ;
memset(dep, -, sizeof(dep[])*(n+));
dep[s] = ;
Q[tail++] = s;
while(front < tail)
{
int u = Q[front++];
for(int i = head[u]; i != -; i = edge[i].next)
{
int v = edge[i].to;
if(edge[i].cap > edge[i].flow && dep[v] == -) {
dep[v] = dep[u] + ;
if(v == t) return true;
Q[tail++] = v;
}
}
}
return false;
}
int dinic(int s, int t, int n) {
int maxflow = ;
while(bfs(s, t, n)) {
for(int i = ; i < n; i++) cur[i] = head[i];
int u = s, tail = ;
while(cur[s] != -)
{
if(u == t)
{
int tp = INF;
for(int i = tail-; i >= ; i--)
tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
maxflow+=tp;
for(int i = tail-; i >= ; i--) {
edge[sta[i]].flow+=tp;
edge[sta[i]^].flow-=tp;
if(edge[sta[i]].cap-edge[sta[i]].flow==)
tail = i;
}
u = edge[sta[tail]^].to;
}
else
if(cur[u] != - && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + == dep[edge[cur[u]].to])
{
sta[tail++] = cur[u];
u = edge[cur[u]].to;
}
else
{
while(u != s && cur[u] == -)
u = edge[sta[--tail]^].to;
cur[u] = edge[cur[u]].next;
}
}
}
return maxflow;
}
int n,m,f;
int fa[MAXN];
int map[][]; int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
} void unio(int x,int y)
{
int a=find(x),b=find(y);
if(a!=b)
fa[a]=b;
} void build(int k)
{
init();
for(int i=;i<=n;++i)
{
addedge(,i,k);
addedge(i+n,*n+,k);
}
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
if(map[i][j])
addedge(i,n+j,);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&f);
for(int i=;i<=n;++i)
fa[i]=i;
memset(map,,sizeof(map));
int a,b;
for(int i=;i<=m;++i)
{
scanf("%d%d",&a,&b);
map[a][b]=;
}
for(int i=;i<=f;++i)
{
scanf("%d%d",&a,&b);
unio(a,b);
}
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
if(find(i)==find(j))
for(int k=;k<=n;++k)
if(map[i][k])
map[j][k]=;
int s=,t=n,ans;
while(s<=t)
{
int mid=(s+t)/;
build(mid);
if(mid*n==dinic(,*n+,*n+))
{
ans=mid;
s=mid+;
}
else
t=mid-;
}
cout<<ans<<endl;
}
return ;
}

hdu3081 Marriage Match II(二分+并查集+最大流)的更多相关文章

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

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

  2. HDU 3081 Marriage Match II (二分+并查集+最大流)

    题意:N个boy和N个girl,每个女孩可以和与自己交友集合中的男生配对子;如果两个女孩是朋友,则她们可以和对方交友集合中的男生配对子;如果女生a和女生b是朋友,b和c是朋友,则a和c也是朋友.每一轮 ...

  3. HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

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

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

  5. hdu3081 Marriage Match II(最大流)

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

  6. HDU 3081 Marriage Match II 二分 + 网络流

    Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女 ...

  7. hdu 3081(二分+并查集+最大流||二分图匹配)

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  8. hdu3081 Marriage Match II

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

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

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

随机推荐

  1. 【tyvj1463】智商问题 [分块][二分查找]

    Background 各种数据结构帝~各种小姊妹帝~各种一遍AC帝~ 来吧! Description 某个同学又有很多小姊妹了他喜欢聪明的小姊妹 所以经常用神奇的函数来估算小姊妹的智商他得出了自己所有 ...

  2. effective java 第2章-创建和销毁对象 读书笔记

    背景 去年就把这本javaer必读书--effective java中文版第二版 读完了,第一遍感觉比较肤浅,今年打算开始第二遍,顺便做一下笔记,后续会持续更新. 1.考虑用静态工厂方法替代构造器 优 ...

  3. 漫谈格兰杰因果关系(Granger Causality)——第一章 野火烧不尽,春风吹又生

    2017年7月9日上午6点10分,先师胡三清同志--新因果关系的提出者.植入式脑部电极癫痫治疗法的提出者.IEEE高级会员,因肺癌医治无效于杭州肿瘤医院去世,享年50岁.余蒙先师厚恩数载,一朝忽闻先师 ...

  4. (转)java提高篇(四)-----理解java的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

  5. 利用python发送邮件

    找了很多使用python发送邮件的文章, 发现写的并不是太全, 导致坑特别多, 刚把这个坑跨过去, 在此记录下来 本代码使用163作为发送客户端, 接收邮箱随意 首先登录163邮箱, 开启POP3/S ...

  6. 36. leetcode 415. Add Strings

    415. Add Strings Given two non-negative integers num1 and num2 represented as string, return the sum ...

  7. whatwg-fetch源码分析

    fetch 是什么 XMLHttpRequest的最新替代技术 fetch优点 接口更简单.简洁,更加语义化 基于promise,更加好的流程化控制,可以不断then把参数传递,外加 async/aw ...

  8. mybatis 详解(六)------通过mapper接口加载映射文件

    通过 mapper 接口加载映射文件,这对于后面 ssm三大框架 的整合是非常重要的.那么什么是通过 mapper 接口加载映射文件呢? 我们首先看以前的做法,在全局配置文件 mybatis-conf ...

  9. LoadRunner入门(二)

    三.设计场景 1.打开Controller 2.选择运行的脚本 3.场景设置 3.1修改场景模式 点击scenario-convert- 修改场景百分比模式 (1)Group Name:脚本名称 (2 ...

  10. C语言程序设计进阶 翁恺 第4周编程练习

    第4周编程练习 查看帮助 返回 第4周编程练习 依照学术诚信条款,我保证此作业是本人独立完成的. 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业 ...