HDU 3081 Marriage Match II 最大流OR二分匹配
Marriage Match IIHDU - 3081
题目大意:每个女孩子可以和没有与她或者是她的朋友有过争吵的男孩子交男朋友,现在玩一个游戏,每一轮每个女孩子都要交一个新的男朋友,问最多可以玩多少轮?
首先要想知道每个女孩子能够和哪些男孩子交朋友,就得通过并查集来处理了,每个女孩子可以交朋友的男孩子,和她是朋友的女孩子同样可以交。
然后就是怎么知道能玩几轮。有两个方法。第一个就是最大流。
具体思路就是二分答案,每个女孩子都可以和能和他交朋友的男孩子建一条流量为1的边,就代表可以和他交一次朋友,然后源点与每个女孩子连一条流量为当前二分的这个答案的边,汇点也与每个男孩子连一条流量为当前二分的这个答案的流,这样的话能每个女孩子能够满流的话就是能够玩这么多轮,当前答案是符合的。
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int N=,M=,inf=;
struct Side{
int v,ne,w;
}S[M];
int n,sn,sb,se,head[N],dep[N],cur[N],fa[N],ok[N][N];
void init()
{
sn=;
sb=,se=*n+;
for(int i=sb;i<=se;i++)
head[i]=-;
}
void add(int u,int v,int w)
{
S[sn].w=w;
S[sn].v=v;
S[sn].ne=head[u];
head[u]=sn++;
}
void addE(int u,int v,int w)
{
add(u,v,w);
add(v,u,);
}
int gui(int x){
return fa[x]==x ? x : fa[x]=gui(fa[x]);
}
void bing(int x,int y)
{
int gx=gui(x),gy=gui(y);
if(gx!=gy)
fa[gx]=gy;
}
void bulidE(int limit)
{
init();
for(int i=;i<=n;i++)
addE(sb,i,limit);
for(int i=;i<=n;i++)
addE(n+i,se,limit);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(ok[i][j])
addE(i,n+j,);
}
bool bfs()
{
for(int i=sb;i<=se;i++)
dep[i]=;
dep[sb]=;
queue<int> q;
q.push(sb);
int u,v;
while(!q.empty()){
u=q.front();
q.pop();
for(int i=head[u];~i;i=S[i].ne){
v=S[i].v;
if(S[i].w>&&!dep[v]){
dep[v]=dep[u]+;
if(v==se)
return true;
q.push(v);
}
}
}
return false;
}
int dfs(int u,int minf)
{
if(u==se||!minf)
return minf;
int v,flow;
for(int &i=cur[u];~i;i=S[i].ne){
v=S[i].v;
if(S[i].w>&&dep[v]==dep[u]+){
flow=dfs(v,min(minf,S[i].w));
if(flow>){
S[i].w-=flow;
S[i^].w+=flow;
return flow;
}
}
}
return ;
}
int dinic()
{
int maxf=,flow;
while(bfs()){
for(int i=sb;i<=se;i++)
cur[i]=head[i];
while(flow=dfs(sb,inf))
maxf+=flow;
}
return maxf;
}
int solve()
{
int l=,r=n,mid,ans=;
while(l<=r){
mid=(l+r)>>;
bulidE(mid);
if(dinic()==n*mid)
ans=mid,l=mid+;
else
r=mid-;
}
return ans;
}
int main()
{
int t,m,f,a,b;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&f);
for(int i=;i<=n;i++){
fa[i]=i;
for(int j=;j<=n;j++)
ok[i][j]=;
}
while(m--){
scanf("%d%d",&a,&b);
ok[a][b]=;
}
while(f--){
scanf("%d%d",&a,&b);
bing(a,b);
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
for(int k=;k<=n;k++)
if(gui(i)==gui(j)&&ok[i][k])
ok[j][k]=;
printf("%d\n",solve());
}
return ;
}
最大流
第二种就是二分匹配。我们每次跑一遍匈牙利为每个女孩子匹配一个男孩子,然后再把他们的关系去掉继续匹配 ,最多能匹配多少轮,就是能玩多少轮。
#include<cstdio>
const int N=;
int n,fa[N],ok[N][N],vis[N],pp[N];
int gui(int x){
return fa[x]==x ? x : fa[x]=gui(fa[x]);
}
void bing(int x,int y)
{
int gx=gui(x),gy=gui(y);
if(gx!=gy)
fa[gx]=gy;
}
int match(int u)
{
for(int i=;i<=n;i++){
if(!vis[i]&&ok[u][i]){
vis[i]=;
if(!pp[i]||match(pp[i])){
pp[i]=u;
return ;
}
}
}
return ;
}
int solve()
{
int ans=,mm;
while(){
mm=;
for(int i=;i<=n;i++){
for(int j=;j<=n;j++)
vis[j]=;
mm+=match(i);
}
if(mm==n)
ans++;
else
break;
for(int i=;i<=n;i++){
ok[pp[i]][i]=;
pp[i]=;
}
}
return ans;
}
int main()
{
int t,m,f,a,b;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&f);
for(int i=;i<=n;i++){
fa[i]=i;
pp[i]=;
for(int j=;j<=n;j++)
ok[i][j]=;
}
while(m--){
scanf("%d%d",&a,&b);
ok[a][b]=;
}
while(f--){
scanf("%d%d",&a,&b);
bing(a,b);
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
for(int k=;k<=n;k++)
if(gui(i)==gui(j)&&ok[i][k])
ok[j][k]=;
printf("%d\n",solve());
}
return ;
}
二分匹配
HDU 3081 Marriage Match II 最大流OR二分匹配的更多相关文章
- 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 二分 + 网络流
Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女 ...
- HDU - 3081 Marriage Match II 【二分匹配】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意 有n对男女 女生去选男朋友 如果女生从来没和那个男生吵架 那么那个男生就可以当她男朋友 女 ...
- HDU 3081 Marriage Match II (二分+并查集+最大流)
题意:N个boy和N个girl,每个女孩可以和与自己交友集合中的男生配对子;如果两个女孩是朋友,则她们可以和对方交友集合中的男生配对子;如果女生a和女生b是朋友,b和c是朋友,则a和c也是朋友.每一轮 ...
- HDU 3081 Marriage Match II (二分+网络流+并查集)
注意 这题需要注意的有几点. 首先板子要快,尽量使用带当前弧优化的dinic,这样跑起来不会超时. 使用弧优化的时候,如果源点设置成0,记得将cur数组从0开始更新,因为有的板子并不是. 其次这题是多 ...
- HDU 3081 Marriage Match II
二分图的最大匹配+并查集 每次匹配完之后,删除当前匹配到的边. #include<cstdio> #include<cstring> #include<cmath> ...
- hdu3081 Marriage Match II(最大流)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Marriage Match II Time Limit: 2000/1000 M ...
随机推荐
- PostgreSQL练习3
select dname,count(ename),avg(sal),sum(sal) from emp e,dept d where e.deptno=d.deptno group by dname ...
- 2019HDU暑期多校训练-1004equation-方程求解
Description You are given two integers N,C and two integer sequences a and b of length N. The sequen ...
- idea 编辑器Git暂存区的使用
平时在开发时候 一般线上环境和线下环境区别会很大,所以一下线下的自己测试环境的代码没有如果提交会影响线上环境,所以一般都会使用git的一个暂存区作为临时存放不需要提交的代码,这样每次提交代码都可以在不 ...
- nginx 实践配置
nginx.conf文件 user root; worker_processes 1; error_log logs/error.log crit; #error_log logs/error.log ...
- 12-MySQL DBA笔记-MySQL复制
第12章 MySQL复制 本章将为读者讲述MySQL的复制技术,首先,介绍最基础的主从复制,它是其他所有复制技术的基础,接着再为读者讲述各种复制架构的搭建,最后,列举了一些常见的复制问题及处理方式.复 ...
- NodeJS express框架的使用
首先,可以通过npm或者淘宝镜像cnpm全局安装epress框架,这里不具体说了 npm install -g expressnpm install -g express-generator 新建一个 ...
- react hooks学习
接触React项目快两个月了,还在研究摸索各种知识点的过程中,充实且幸福. 在项目中学习新知识,还是很有效率的,一边写项目,一边实验新的知识点,比如react hooks!嘻嘻嘻~~~ 写了好一段时间 ...
- mysql管理工具之pt
之前我一直用Seconds_behind_master来衡量主从的延迟,今天看到文档,才觉得多么不可靠!以下是官方文档的描述: In essence, this field measures the ...
- 交换机配置-----monitor session
目录 交换机配置-----monitor 1.前言 2.monitor session的作用 3.配置命令 4.使用 交换机配置-----monitor 1.前言 本文章适用于Dell Network ...
- String 类的常用方法都有那些?(未完成)
String 类的常用方法都有那些?(未完成)