注意

这题需要注意的有几点。

  • 首先板子要快,尽量使用带当前弧优化的dinic,这样跑起来不会超时。
  • 使用弧优化的时候,如果源点设置成0,记得将cur数组从0开始更新,因为有的板子并不是。
  • 其次这题是多组样例输入,所以每次需要清空head数组,pre数组,deep数组,vis数组等等,以及建图之前将cnt设置为0。

题意

有n个女孩和n个男孩,给出哪些女孩和哪些男孩从未发生冲突,以及女孩之间的朋友关系,朋友关系是传递的。

每次所有女孩都选择不同一个男孩作为自己的伴侣,问能选择几轮?

女孩选择男孩的条件是,女孩从未和该男孩发生冲突,或者她的朋友从未和该男孩发生冲突。

思路

  1. 用并查集将女孩分组,同一个组内的女孩,共享他们喜欢的男孩。
  2. 然后就是二分图匹配,建立源点和汇点,源点连接女孩,汇点连接男孩(以下简称源点汇点路径),女孩喜欢男孩,就建一条边。

    如果源点汇点路径权值为1,那么这个最大流跑出来就是女孩和男孩的最大匹配方案数。
  3. 这题问的是每次每位女孩都选择不同的男孩,并且每位女孩都要有人能匹配,所以,我们二分源点汇点路径的权值大小。

    易知,如果源点汇点路径权值 k <= ans ,那么最大流 maxflow==n*k 。

    因为每个人跑都是满流,所以此时可以尝试将k增加,如果不等于,说明k值过大,应将k值减小。

    AC 31ms
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std; const int INF=0x3f3f3f3f;
const int maxn=210;
const int maxm=21000;
bool bridge[maxn][maxn];
int pre[maxn]; struct Edge {
int from,to,cap,flow;
}; struct Dinic {
Edge edge[maxm];
int next[maxm];
int head[maxn];
int deep[maxn];
int cur[maxn];
int vis[maxn];
int n,m,s,t,cnt=0; void init_point(int nn,int mm ,int ss,int tt) {
n=nn;
m=mm;
s=ss;
t=tt;
} void init() {
memset(head,-1,sizeof(head));
cnt=0;
} void addEdge(int u,int v,int w) {
edge[cnt].cap=w;
edge[cnt].flow=0;
edge[cnt].from=u;
edge[cnt].to=v;
next[cnt]=head[u];
head[u]=cnt++; edge[cnt].cap=0;
edge[cnt].flow=0;
edge[cnt].from=v;
edge[cnt].to=u;
next[cnt]=head[v];
head[v]=cnt++;
} void build(int value) {
init();
for (int i=1;i<=n;i++) {
addEdge(s,i,value);
}
for (int i=n+1;i<=2*n;i++) {
addEdge(i,t,value);
}
for (int i=1;i<=n;i++) {
for (int j=n+1;j<=2*n;j++) {
if (bridge[i][j]) {
addEdge(i,j,1);
}
}
}
// for (int i=0;i<=n;i++) {
// printf("%d:",i);
// for (int j=head[i];j!=-1;j=next[j]) {
// printf("%d %d %d ",edge[j].to,edge[j].cap,edge[j].flow);
// }
// printf("\n");
// }
} bool bfs() {
memset(vis,0,sizeof(vis));
memset(deep,0,sizeof(deep));
queue<int> q;
deep[s]=0;
vis[s]=true;
q.push(s);
while (!q.empty()) {
int u=q.front();
q.pop();
for (int i=head[u];i!=-1;i=next[i]) {
Edge &e=edge[i];
if (!vis[e.to]&&e.cap>e.flow) {
deep[e.to]=deep[u]+1;
vis[e.to]=true;
q.push(e.to);
}
}
}
return vis[t];
} int dfs(int u,int in) {
if (u==t||in==0) {
return in;
}
int out=0,f;
for (int& i=cur[u];i!=-1;i=next[i]) {
int v=edge[i].to;
if (deep[v]==deep[u]+1&&(f=dfs(v,min(in,edge[i].cap-edge[i].flow)))>0) {
edge[i].flow+=f;
edge[i^1].flow-=f;
out+=f;
in-=f;
if (in==0) {
break;
}
}
}
return out;
} int maxflow() {
int ans=0;
while (bfs()) {
for (int i=0;i<=2*n+1;i++) {
cur[i]=head[i];
}
ans+=dfs(s,INF);
}
return ans;
} }DC; int findset(int x)
{
if (x==pre[x]) {
return x;
}
return pre[x]=findset(pre[x]);
} void unions(int a,int b)
{
int x=findset(a);
int y=findset(b);
if (x!=y) {
pre[x]=y;
}
} int main()
{
int T,f,n,m,x,y;
scanf("%d",&T);
while (T--) {
scanf("%d%d%d",&n,&m,&f);
DC.init_point(n,m,0,2*n+1);
memset(bridge,0,sizeof(bridge));
for (int i=0;i<maxn;i++) {
pre[i]=i;
}
for (int i=0;i<m;i++) {
scanf("%d%d",&x,&y);
bridge[x][y+n]=true;
}
for (int i=0;i<f;i++) {
scanf("%d%d",&x,&y);
unions(x,y);
}
for (int i=1;i<=n;i++) {
for (int j=i+1;j<=n;j++) {
if (findset(i)==findset(j)) {
for (int k=n+1;k<=2*n;k++) {
if (bridge[i][k]||bridge[j][k]) {
bridge[i][k]=bridge[j][k]=true;
}
}
}
}
}
int l=0,r=100,ans,mid;
while (l<=r) {
mid=(l+r)>>1;
DC.build(mid);
if (DC.maxflow()==n*mid) {
ans=mid;
l=mid+1;
}
else {
r=mid-1;
}
}
printf("%d\n",ans);
}
return 0;
}

HDU 3081 Marriage Match II (二分+网络流+并查集)的更多相关文章

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

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

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

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

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

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

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

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

  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 最大流OR二分匹配

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

  7. HDU - 3081 Marriage Match II 【二分匹配】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意 有n对男女 女生去选男朋友 如果女生从来没和那个男生吵架 那么那个男生就可以当她男朋友 女 ...

  8. HDU 3081 Marriage Match II

    二分图的最大匹配+并查集 每次匹配完之后,删除当前匹配到的边. #include<cstdio> #include<cstring> #include<cmath> ...

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

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

随机推荐

  1. 第七章 类(class)7.1 笔记

    最好不要把对象的定义和类的定义放在一起,这么做无异于把两种不同实体的定义混在了一条语句里,一会定义类,一会又定义变量,显然这是一种不被建议的行为. 类的定义最后要加上分号(:) 成员函数的声明必须放在 ...

  2. C# 选取本月周六日方法

    用于工作: 1.取本月第一天就是1号 2.取下月第一天再减去一天 就是本月最后一天 3.从月头遍历至月末,判断周几 代码如下: #region 提取本月周六日 DateTime start = new ...

  3. 每天进步一点点------Allegro 蛇形走线

    对于高速数据总线,如果芯片内部没有延时调节功能,通常使用蛇形走线来调整延时以满足时序要求,也就是通常所说的等长线.蛇形走线的目的是调整延时,所以这一类网络都有延迟或相对延迟约束.所以在做蛇形走线调整时 ...

  4. robots.txt 让搜索引擎不再收录网站

    有没有担心过自己的隐私会在强大的搜索引擎面前无所遁形?想象一下,如果要向世界上所有的人公开你的私人日记,你能接受吗?的确是很矛盾的问题,站长们大都忧虑“如何让搜索引擎收录的我的网站?”,而我们还是要研 ...

  5. poj 3057(bfs+二分匹配)

    题目链接:http://poj.org/problem?id=3057 题目大概意思是有一块区域组成的房间,房间的边缘有门和墙壁,'X'代表墙壁,'D'代表门,房间内部的' . '代表空区域,每个空区 ...

  6. 普及C组第二题(8.5)

    1565. [GDKOI]神秘山庄 (Standard IO) 时间限制: 1000 ms  空间限制: 262144 KB 题目: 翠亨村是一个神秘的山庄,并不是因为它孕育了伟人孙中山,更神秘的是山 ...

  7. 计算几何-UVa10652

    This article is made by Jason-Cow.Welcome to reprint.But please post the article's address. 题意见白书,P2 ...

  8. JVM的方法区和永久带是什么关系?

    什么是方法区? 方法区(Method Area)是jvm规范里面的运行时数据区的一个组成部分,jvm规范中的运行时数据区还包含了:pc寄存器.虚拟机栈.堆.方法区.运行时常量池.本地方法栈. 方法区存 ...

  9. ISR吞吐性能问题

    ISR大致可以分几类: Cisco 860.880.890 ISR1800 (fixed).1800 (modular).2800.3800 Series ISR1900.2900.3800.3900 ...

  10. c++中sort函数调用报错Expression : invalid operator <的内部原理

    当我们调用sort函数进行排序时,中的比较函数如果写成如下 bool cmp(const int &a, const int &b) { if(a!=b) return a<b; ...