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 ...
随机推荐
- S03_CH02_AXI_DMA PL发送数据到PS
S03_CH02_AXI_DMA PL发送数据到PS 1.1概述 本课程的设计原理分析. 本课程循序渐进,承接<S03_CH01_AXI_DMA_LOOP 环路测试>这一课程,在DATA ...
- S02_CH16 等精度频率计实验
S02_CH16 等精度频率计实验 在了解了AXI总线之后,今天我们自己动手设计一个带AXI4-Lite总线的IP,来完成频率计的实验. 频率计虽然小,但是也算五脏俱全,涉及到zynq的方方面面,比如 ...
- 牛客 216D 消消乐 (二分图最小点覆盖)
大意: 给定棋盘, 每次消除一行或一列, 求最小次数使得消除完所有'*'. 裸的二分图最小点覆盖. 二分图的最小点覆盖等于最大匹配, 输出方案时从所有左部未盖点开始标记交替路上的点, 最后左部所有未标 ...
- hdu 3500 还是搜索
这道题目由于每走一步的时候毛毛球是可以变换的 换言之 主体不唯一 所以这里搜索的设计有变化 再就是几个回溯的过程要注意.,. 小心使得万年船 #include <iostream> #i ...
- C# switch语句的使用
1 今天我们来学习switch 语句的使用,switch 语句和if else 类似 switch 语句主要的作用是用于来判断在规定条件下 根据你的选择来执行switch 语句下面case :的 ...
- [转载]SSD原理与实现
[转载]SSD原理与实现 这里只mark一下,对原论文讲解的很好的博文 https://zhuanlan.zhihu.com/p/33544892 这里有一个关于SSD的很好的程序实现,readme里 ...
- LEANGOO用户设置
转自:https://www.leangoo.com/leangoo_guide/leangoo_guide_kanban_user.html#toggle-id-7 1. 点击屏幕右上角头像或用户名 ...
- 记录一次ABP下载模板的坑
1.拉取ABP官网的模板的最新代码,我的代码结构是这样的 https://aspnetboilerplate.com/Templates 环境安装的部分我就不说明了.node.js npm 等等部分 ...
- Vsftpd Nginx
Linux(CentOS-6.10)下安装Vsftpd Nginx 1:创建FTP专属的账户和密码[root@localhost ~]# useradd ftpuser[root@localhost ...
- IDEA设置CodeGlance颜色
CodeGlance是IDEA的mini地图插件, 默认情况下, 其颜色和编辑框的颜色基本一致, 而安装CodeGlance就是为了方便滚动框的上下拖拉, 颜色一致的话会将这种CodeGlance比拖 ...