题意: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. maven + hessian 简单样例

    项目结构例如以下: pom.xml 内容: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&quo ...

  2. Redis异构集群数据在线迁移工具Redis-Migrate-Tool【转】

    摘要:Redis-Migrate-Tool(后面都简称RMT),是唯品会开源的redis数据迁移工具,主要用于异构redis集群间的数据在线迁移,即数据迁移过程中源集群仍可以正常接受业务读写请求,无业 ...

  3. jquery与javescript的区别(一)

    一.找元素: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&g ...

  4. 各种层次NET人应该知道些什么?

    A.任何一个使用.NET的人 1.描述线程与进程的区别? 2.什么是Windows服务,它的生命周期与标准的EXE程序有什么不同 ? 3.Windows上的单个进程所能访问的最大内存量是多少?它与系统 ...

  5. Myeclipse中js总是报错

    1.右键选择 MyEclipse-->Exclude From Validation .2.再右键选择 MyEclipse-->Run Validation 即可.

  6. Javaweb Tomcat 项目部署方式

    一.静态部署 1.直接将web项目文件件拷贝到webapps 目录中     Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应用.所以可以将JSP ...

  7. 2017 Multi-University Training Contest - Team 1—HDU6035

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:一棵树有n个点,每个点有自己的颜色,任意两个不同的点可以组成一条路径.也就是说一共有n(n ...

  8. 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'information_schema.PROFILING.SEQ' which is not functionally dependent on columns in GROUP BY clause

    解决方法一: SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); 优点:不用重启mysql 缺点:重启mysql后还会 ...

  9. python console

    print(sys.stdout.encoding, locale.getpreferredencoding ()) windows console : chcp 65001; 在设置了这个环境变量时 ...

  10. 在Win10上,Android Studio检测不到设备的解决方案

    下载ADB驱动程序安装器 运行ADBDriverInstaller.exe,可以看到设备状态不正常,点击Install 可能会弹出这样的对话框,点击Got it, Restart Now,按照提示完成 ...