HDU 3081 Marriage Match II (二分+网络流+并查集)
注意
这题需要注意的有几点。
- 首先板子要快,尽量使用带当前弧优化的dinic,这样跑起来不会超时。
- 使用弧优化的时候,如果源点设置成0,记得将cur数组从0开始更新,因为有的板子并不是。
- 其次这题是多组样例输入,所以每次需要清空head数组,pre数组,deep数组,vis数组等等,以及建图之前将cnt设置为0。
题意
有n个女孩和n个男孩,给出哪些女孩和哪些男孩从未发生冲突,以及女孩之间的朋友关系,朋友关系是传递的。
每次所有女孩都选择不同一个男孩作为自己的伴侣,问能选择几轮?
女孩选择男孩的条件是,女孩从未和该男孩发生冲突,或者她的朋友从未和该男孩发生冲突。
思路
- 用并查集将女孩分组,同一个组内的女孩,共享他们喜欢的男孩。
- 然后就是二分图匹配,建立源点和汇点,源点连接女孩,汇点连接男孩(以下简称源点汇点路径),女孩喜欢男孩,就建一条边。
如果源点汇点路径权值为1,那么这个最大流跑出来就是女孩和男孩的最大匹配方案数。 - 这题问的是每次每位女孩都选择不同的男孩,并且每位女孩都要有人能匹配,所以,我们二分源点汇点路径的权值大小。
易知,如果源点汇点路径权值 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 (二分+网络流+并查集)的更多相关文章
- HDU 3081 Marriage Match II 二分 + 网络流
Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女 ...
- HDU 3081 Marriage Match II (二分+并查集+最大流)
题意:N个boy和N个girl,每个女孩可以和与自己交友集合中的男生配对子;如果两个女孩是朋友,则她们可以和对方交友集合中的男生配对子;如果女生a和女生b是朋友,b和c是朋友,则a和c也是朋友.每一轮 ...
- HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)
HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...
- HDU 3081 Marriage Match II(二分法+最大流量)
HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个 ...
- HDU 3081 Marriage Match II (二分图,并查集)
HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...
- HDU 3081 Marriage Match II 最大流OR二分匹配
Marriage Match IIHDU - 3081 题目大意:每个女孩子可以和没有与她或者是她的朋友有过争吵的男孩子交男朋友,现在玩一个游戏,每一轮每个女孩子都要交一个新的男朋友,问最多可以玩多少 ...
- HDU - 3081 Marriage Match II 【二分匹配】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意 有n对男女 女生去选男朋友 如果女生从来没和那个男生吵架 那么那个男生就可以当她男朋友 女 ...
- HDU 3081 Marriage Match II
二分图的最大匹配+并查集 每次匹配完之后,删除当前匹配到的边. #include<cstdio> #include<cstring> #include<cmath> ...
- Marriage Match II(二分+并查集+最大流,好题)
Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Othe ...
随机推荐
- jvm(1):内存结构
JVM内存结构 JVM内存的运行时数据区: 线程私有(在线程启动时创建) 程序计数器Program Counter Register 一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器, ...
- 【译】从 Rust 到不只是 Rust:PHP 语言领域
From Rust to beyond: The PHP galaxy 译文 原文地址:https://mnt.io/2018/10/29/from-rust-to-beyond-the-php-ga ...
- unittest学习3-测试组件setup、teardown
unittest的测试用例执行时都可以设置setup.teardown,用来初始化测试开始和测试结束关闭,例如: import unittest class MyTestCase(unittest.T ...
- webview在compileSdkVersion 大于等于23 android6.0以上系统执行js代码异常,但是在compileSdkVersion小于23 android6.0以下系统却执行正常问题
问题分析: 在compileSdkVersion>=23 android6.0以上webview.loadUrl用这个方法执行js时会将js中的一些代码当做特殊字符处理, 比如js中var t= ...
- 吴裕雄 python 机器学习——局部线性嵌入LLE降维模型
# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt from sklearn import datas ...
- redis环境搭建学习笔记
学习环境为windows.java环境 一.学习教程: 1.菜鸟教程:http://www.runoob.com/redis/redis-tutorial.html 2.redis中文网:http:/ ...
- bootstrap创建带遮罩层的进度条
<div class="modal fade" id="loadingModal"> <div style="width: 200p ...
- 安装Linux系统后配置的一般步骤
安装linux后配置的一般步骤 最近在尝试不同的linux系统,记录一下安装完linux之后常用的软件的安装方法 1.源的更新 ubuntu 源的更新方法 参考(没有测试过,但是都大同小异,不行就换一 ...
- Spring Boot 编辑器 IDEA 免费许可申请
最近 IDEA 陆续到期(试用版)听说可以申请开源许可,试试吧. 点击 https://www.jetbrains.com/shop/eform/opensource?product=ALL 填写相关 ...
- springMVC的概念
1,完成一次web请求的过程 Web浏览器发起请求 Web服务器接收请求并处理请求,最后产生响应(一般为html).web服务器处理完成后,返回内容给web客户端,客户端对接收的内容进行处理并显示出来 ...