注意

这题需要注意的有几点。

  • 首先板子要快,尽量使用带当前弧优化的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. python selenium设计模式POM

    POM模式是什么 页面对象模型(POM)是一种设计模式,用来管理维护一组web元素集的对象库 在POM模式下,应用程序的每一个页面都有一个对的page class 每一个page class维护着该w ...

  2. AcWing 前缀和 一维加二维

    一维 #include<bits/stdc++.h> using namespace std; ; int n,m; int a[N],s[N]; int main(){ ios::syn ...

  3. 16day 引号符号系列

    '' 输出的信息,所见即所得 [root@oldboyedu oldboy]# echo 'oldboy $LANG $oldgirl' oldboy $LANG $oldgirl "&qu ...

  4. JFrog推出全球首个支持混合云架构,端到端的通用DevOps平台 ——JFrog Platform

            JFrog Platform,基于屡获殊荣的JFrog Artifactory制品仓库的独特能力,通过多合一的体验提供DevSecOps.CI / CD和软件分发的解决方案. 2020 ...

  5. bzoj4765: 普通计算姬 (分块 && BIT)

    最近一直在刷分块啊 似乎感觉分块和BIT是超级棒的搭档啊 这道题首先用dfs预处理一下 得到每一个sum值 此时查询是O(1)的  (前缀和乱搞什么的 但是修改需要O(n) (需要修改该节点所有祖先的 ...

  6. VS“无法查找或打开PDB文件”是怎么回事?如何解决

    有时候,我们使用 VS(Visual Studio)编译程序时会出现“无法查找或打开PDB文件”的提示,并且此时程序会生成失败,无法运行,如下图所示: 大家不要惊慌,出现这种提示并不是代码写错了,而是 ...

  7. 励志写一篇有味道的博文------json

    之前有更古老的数据交互中间键xml,但是由于比较复杂后来出现了json json :轻量级数据交换格式 json与python数据对比 json        python object      d ...

  8. IDEA格式化代码快捷键失灵原因

    网易云音乐快捷键与IDEA快捷键冲突了!!!!!!!坑爹

  9. css: transform导致文字显示模糊

    css: transform导致文字显示模糊 有人认为模糊的原因是:"transform时div的宽度或者高度并不是偶数,偏移 50% 之后,像素点不是整数,和显示像素没有对上". ...

  10. 关于Sublime如何配置C++环境的问题

    前言 传说sublime是全球最好的编辑器,可是只是编辑器啊!!!如果要运行,对于我们这些蒟蒻来说,不得不去使用DEV_C++.我们总是幻想能让sublime变成一个轻量级IDE,那该多好啊!!! 那 ...