题意:N个boy和N个girl,每个女孩可以和与自己交友集合中的男生配对子;如果两个女孩是朋友,则她们可以和对方交友集合中的男生配对子;如果女生a和女生b是朋友,b和c是朋友,则a和c也是朋友.每一轮配对结束后(每个人都找到自己的对象),在开始新的一轮配对.求最大能进行多少轮完整的游戏.

分析:用最大流解决该问题,若假设能进行k轮游戏,则由源点向每个女生建一条容量为k的边,每个男生也向汇点建一条容量为k的边,对于每个女生,向其能够配对的男生连一条容量为1的边.最后跑出最大流若为n*k则表示游戏能够进行k轮.

确定了这点之后,二分搜答案.

还有一个问题就是,如何通过伙伴关系来确定女生能配对的所有男生? 有并查集和传递闭包两种方法,复杂度是差不多.属于一个集合中的女生,则她们的匹配对象集合就是所有人对象集合的并集.

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN=10010;//点数的最大值
const int MAXM=400010;//边数的最大值
#define captype int struct SAP_MaxFlow{
struct EDGE{
int to,next;
captype cap;
}edg[MAXM];
int eid,head[MAXN];
int gap[MAXN];
int dis[MAXN];
int cur[MAXN];
int pre[MAXN]; void init(){
eid=0;
memset(head,-1,sizeof(head));
}
void AddEdge(int u,int v,captype c,captype rc=0){
edg[eid].to=v; edg[eid].next=head[u];
edg[eid].cap=c; head[u]=eid++;
edg[eid].to=u; edg[eid].next=head[v];
edg[eid].cap=rc; head[v]=eid++;
}
captype maxFlow_sap(int sNode,int eNode, int n){//n是包括源点和汇点的总点个数,这个一定要注意
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
memcpy(cur,head,sizeof(head));
pre[sNode] = -1;
gap[0]=n;
captype ans=0;
int u=sNode;
while(dis[sNode]<n){
if(u==eNode){
captype Min=INF ;
int inser;
for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to])
if(Min>edg[i].cap){
Min=edg[i].cap;
inser=i;
}
for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to]){
edg[i].cap-=Min;
edg[i^1].cap+=Min;
}
ans+=Min;
u=edg[inser^1].to;
continue;
}
bool flag = false;
int v;
for(int i=cur[u]; i!=-1; i=edg[i].next){
v=edg[i].to;
if(edg[i].cap>0 && dis[u]==dis[v]+1){
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag){
u=v;
continue;
}
int Mind= n;
for(int i=head[u]; i!=-1; i=edg[i].next)
if(edg[i].cap>0 && Mind>dis[edg[i].to]){
Mind=dis[edg[i].to];
cur[u]=i;
}
gap[dis[u]]--;
if(gap[dis[u]]==0) return ans;
dis[u]=Mind+1;
gap[dis[u]]++;
if(u!=sNode) u=edg[pre[u]^1].to; //退一条边
}
return ans;
}
}F; bool G[205][205];
int fa[105]; int Find(int x){
return fa[x]==-1? x:fa[x] = Find(fa[x]);
} void Union(int x,int y)
{
x = Find(x), y = Find(y);
if(x!=y) fa[x] = y;
} bool check(int n,int limit){
F.init();
int st =0,ed = 2*n+1;
for(int i=1;i<=n;++i){
for(int j = n+1;j<=2*n;++j){
if(G[i][j]) F.AddEdge(i,j,1);
}
}
for(int i=1;i<=n;++i) F.AddEdge(st,i,limit);
for(int i=n+1;i<=2*n;++i) F.AddEdge(i,ed,limit);
int res = F.maxFlow_sap(st,ed,2*n+2);
return res == n*limit;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T; scanf("%d",&T);
int n,m,f,u,v,tmp;
while(T--){
scanf("%d %d %d",&n,&m,&f);
memset(G,0,sizeof(G));
memset(fa,-1,sizeof(fa));
for(int i =1;i<=m;++i){
scanf("%d %d",&u,&v);
G[u][v+n] = 1;
}
for(int i=1;i<=f;++i){
scanf("%d %d",&u,&v);
Union(u,v);
}
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
if(Find(i)==Find(j)){
for(int k=n+1;k<=2*n;++k){
G[i][k] = G[j][k] = (G[i][k] || G[j][k]);
}
}
}
}
int L = 0,R =100,mid,ans=0;
while(L<=R){
mid =(L+R)>>1;
if(check(n,mid)){
ans = mid;
L= mid+1;
}
else {
R= mid-1;
}
}
printf("%d\n",ans);
}
return 0;
}

HDU 3081 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. hdu3081 Marriage Match II(二分+并查集+最大流)

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

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

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

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

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

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

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

  6. HDU 3081 Marriage Match II(二分法+最大流量)

    HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个 ...

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

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

  8. HDU 3081 Marriage Match II (二分+网络流+并查集)

    注意 这题需要注意的有几点. 首先板子要快,尽量使用带当前弧优化的dinic,这样跑起来不会超时. 使用弧优化的时候,如果源点设置成0,记得将cur数组从0开始更新,因为有的板子并不是. 其次这题是多 ...

  9. HDU 3081 Marriage Match II 最大流OR二分匹配

    Marriage Match IIHDU - 3081 题目大意:每个女孩子可以和没有与她或者是她的朋友有过争吵的男孩子交男朋友,现在玩一个游戏,每一轮每个女孩子都要交一个新的男朋友,问最多可以玩多少 ...

随机推荐

  1. 漫游Kafka设计篇之消息传输的事务定义(5)

    之前讨论了consumer和producer是怎么工作的,现在来讨论一下数据传输方面.数据传输的事务定义通常有以下三种级别: 最多一次: 消息不会被重复发送,最多被传输一次,但也有可能一次不传输. 最 ...

  2. JavaWeb的编码问题

    http://blog.csdn.net/yuhaiqiang_123/article/details/51811419

  3. Maven项目POM.xml详解

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  4. WebService远程调用(命令行调用)

    远程调用webservice 方法, 通过wsdl命令,生成webservice 对应asmx 文件的对应类(cs文件),然后将此cs文件引用到当前项目中,项目其他地方需要调用webservice方法 ...

  5. tomcat启动后,页面浏览时报错 Unable to compile class for JSP的解决方案

    转:tomcat启动后,页面浏览时报错 Unable to compile class for JSP的解决方案 检查tomcat与web工程对应版本,tomcat中对应版本的jar包拷贝到web工程 ...

  6. c++ const(不断跟新)

    1.把一个 const 对象的地址赋给一个普通的.非 const 对象的指针也会导致编译时的错误: const double pi = 3.14; double *ptr = π // error: ...

  7. forEach循环dom

    大家都知道forEach是循环数组用的,而且很方便,可以丢掉for循环了,但是它不能循环Dom元素.其实我们可以利用call来完成forEach循环Dom; html结构: <ul class= ...

  8. ios 对日期的处理(包括计算昨天时间、明天时间)

    NSDate存储的是世界标准时(UTC),输出时需要根据时区转换为本地时间 Dates NSDate类提供了创建date,比较date以及计算两个date之间间隔的功能.Date对象是不可改变的. 如 ...

  9. Caused by: java.lang.ClassNotFoundException[android的终极解决错误]

    from:http://blog.csdn.net/changemyself/article/details/7861525 08-13 18:29:22.924: E/AndroidRuntime( ...

  10. LAMP集群项目二 初始化系统

    1.关闭防火墙 /etc/init.d/iptables stop chkconfig iptables off 2.关闭selinux cat /etc/selinux/config #查看状态 s ...