HDOJ 3081 - Marriage Match II 并查集+构图最大流...
来源:互联网 发布:本地端口拒绝访问 编辑:程序博客网 时间:2024/06/08 11:45
题意:
有N个女孩和N个男孩玩过家家...某些女孩之间存在朋友关系..并且朋友关系可以传递.比如a和b是朋友..b和c是朋友...那么a,c就会是朋友...一个女生会选一个男生做男友必须这个男生至少和她朋友圈包括自己的某个女孩从没吵过架...每一轮进行一次配对...每轮必须每对都不同..问最多可以配对多少轮...
题解:
女孩间的朋友关系用并查集维护..二分轮数..设当前枚举的轮数为M.构图..超级源点向每个女孩做边容量为M..每个女孩向可以配对的男孩做边容量为1..每个男孩向超级汇点做边...容量为M..跑最大流..若MaxFlow==N*M则说明是可以到达该轮数的..
据说还可以直接用匈牙利搞..每次找到最大匹配后把匹配的边删去..继续做..做了多少次找不到最大匹配等于N了就说明轮数找到了...
Program:
#include<iostream>#include<algorithm>#include<stdio.h>#include<string.h>#include<math.h>#include<queue>#define MAXN 2005#define MAXM 20000005#define oo 1000000007#define ll long longusing namespace std; struct Dinic { struct node { int x,y,c,next; }line[MAXM]; int Lnum,_next[MAXN],dis[MAXN],dp[MAXN]; bool inqueue[MAXN]; void initial(int n) { for (int i=0;i<=n;i++) _next[i]=-1; Lnum=-1; } void addline(int x,int y,int c) { line[++Lnum].next=_next[x],_next[x]=Lnum; line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c; line[++Lnum].next=_next[y],_next[y]=Lnum; line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0; } bool BFS(int s,int e) { queue<int> Q; while (!Q.empty()) Q.pop(); memset(dis,0,sizeof(dis)); dis[s]=1,Q.push(s); while (!Q.empty()) { int h,k; h=Q.front(),Q.pop(); if (h==e) return dis[e]; for (k=_next[h];k!=-1;k=line[k].next) if (line[k].c && !dis[line[k].y]) dis[line[k].y]=dis[h]+1,Q.push(line[k].y); } return false; } int dfs(int x,int flow,int e) { if (x==e) return flow; int temp,cost=0; for (int k=_next[x];k!=-1;k=line[k].next) if (line[k].c && dis[line[k].y]==dis[x]+1) { temp=dfs(line[k].y,min(flow-cost,line[k].c),e); if (temp) { line[k].c-=temp,line[k^1].c+=temp; cost+=temp; if (flow==cost) return cost; }else dis[line[k].y]=-1; } return cost; } int MaxFlow(int s,int e) { int MaxFlow=0; while (BFS(s,e)) MaxFlow+=dfs(s,oo,e); return MaxFlow; } }T;int father[105];bool g[105][105];int getfather(int x){ if (father[x]==x) return x; return father[x]=getfather(father[x]);}bool judge(int n,int M){ int i,j,s,e; s=n*2+5,e=s+1,T.initial(e); for (i=1;i<=n;i++) T.addline(s,i,M),T.addline(i+n,e,M); for (i=1;i<=n;i++) for (j=1;j<=n;j++) if (g[father[i]][j]) T.addline(i,j+n,1); return T.MaxFlow(s,e)==n*M;}int main() { int C,cases,n,m,f,i,x,y; scanf("%d",&C); for (cases=1;cases<=C;cases++) { scanf("%d%d%d",&n,&m,&f); memset(g,false,sizeof(g)); while (m--) { scanf("%d%d",&x,&y); g[x][y]=true; } for (i=1;i<=n;i++) father[i]=i; while (f--) { scanf("%d%d",&x,&y),x=getfather(x),y=getfather(y); father[x]=y; for (i=1;i<=n;i++) g[y][i]=g[y][i]|g[x][i]; } for (i=1;i<=n;i++) getfather(i); int l=0,r=oo,mid; while (r-l>1) { mid=l+r>>1; if (judge(n,mid)) l=mid; else r=mid; } printf("%d\n",l); } return 0;}
- HDOJ 3081 - Marriage Match II 并查集+构图最大流...
- 【hdoj 3081】Marriage Match II 【并查集orfloyd +完美匹配】or【最大流+二分+并查集】
- 【hdu3081】【二分法】【最大流】【并查集】Marriage Match II
- 并查集+最大流-HDU-3038-Marriage Match II
- hdu3081 Marriage Match II 最大流+二分+并查集
- hdoj 3081 Marriage Match II 【二分查找+ 最大流 + 并查集 or floyd】【二分图求最大匹配 + 并查集 or floyd】
- hdu 3081 Marriage Match II(二分最大流+并查集+判断满流)
- HDU 3081Marriage Match II(二分+并查集+网络流之最大流)
- hdu 3081 Marriage Match II 【图论-网络流-最大流+并查集】
- hdu 3081 Marriage Match II(最大流 + 二分 + 并查集)
- HDU 3081 Marriage Match II —并查集,最大流
- HDU 3081 Marriage Match II(二分+并查集+最大流)
- HDU 3081 Marriage Match II [二分最大流]+并查集?807★
- 【HDU】 3081 Marriage Match II (最大流+并查集)
- HUD -- 3081 Marriage Match II(最大流+二分+并查集)
- HDU 3081 Marriage Match II(最大流 + 并查集)
- hdu 3081 Marriage Match II (二分+最大流+并查集)
- HDU3081 3081 Marriage Match II(中等,好题)([二分最大流]+并查集)
- Android画图之Matrix(一)
- Why Conventions Matter
- 设计模式——模板方法模式
- 黑马程序员_JAVA笔记20——IO流
- poj3126解题报告
- HDOJ 3081 - Marriage Match II 并查集+构图最大流...
- 找出数组中重复次数最多的数
- hdu 4465 Candy(2012 ACM-ICPC 成都现场赛)
- 关于using的介绍 Web.config配置 App.config数据库的链接文件的配置
- jQuery为开发插件提拱了两个方法
- git clone: error: RPC failed; result=18, HTTP code = 200 解决办法
- 了解Oracle补丁以及应用方法(案例讲解)
- 生成直线的Bresenham算法
- 设计模式原则详解