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 ...
随机推荐
- 手机网站支付如何接入支付宝简易版支付功能PHP版
接入支付宝准备工作:(关于账号可以是个体商户也可以是企业账号但必须有营业执照) 1.登录蚂蚁金服开放平台 2.创建应用,应用分类网页应用和移动应用.应用提交审核审核通过后得到Appid才能调用相应的 ...
- 初识机器学习——概念介绍(imooc笔记)
前言 imooc的机器学习一个最基本的介绍类课程,http://www.imooc.com/learn/717 ,不怎么涉及具体的算法或实现,只是讲了讲一些理论概念. 概述 机器学习: 利用计算机从历 ...
- 怎样使用js将文本复制到系统粘贴板中
需要使用到三个document方法: 1. document.execCommand(); 执行某个命令 2. document.queryCommandSupported(); 检测浏览器是否支持某 ...
- 手机号码归属地查询API
<?php function object_array($array){ if(is_object($array)){ $array = (array)$array; } if(is_array ...
- js摄像头
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- 梯度直方图(HOG,Histogram of Gradient)
1.介绍 HOG(Histogram of Oriented Gradient)是2005年CVPR会议上,法国国家计算机科学及自动控制研究所的Dalal等人提出的一种解决人体目标检测的图像描述子,该 ...
- c++11 用户定义字面量
c++11 用户定义字面量 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inc ...
- RPC、RMI、REST的区别
初入职场,接触了不少企业常用的技术,与学校实训使用的技术有很大差异,在这里记录一下RPC.RMI与REST的区别. 概念 RPC(Remote Procedure Call,远程过程调用) 一种通过从 ...
- echarts —— tooltip 鼠标悬浮显示提示框属性
最近一直在使用echarts,当然也被其中的各种属性整的头大,记录一下其中遇到的问题. tooltip:鼠标悬浮时显示的提示框. 今天想要记录的是[自定义提示框的内容],如下图,鼠标悬浮时提示框内显示 ...
- extension(类扩展)和 category(类别)
extension(类扩展) 简单来说,extension在.m文件中添加,所以其权限为private,所以只能拿到源码的类添加extension.另外extension是编译时决议,和interfa ...