题目链接:点击查看

题目大意:n个男生和n个女生配对,配对规则如下:

  1. 每个女生都可以选择没有吵过架的男生匹配
  2. 若女生A的好朋友是女生B,且女生B没有和男生C吵过架,则女生A也可以和男生C匹配

现在问最多可以匹配多少轮,要求每轮必须完全匹配,且每个男生匹配的女生以及每个女生匹配的男生都不能重复,求最大匹配轮数

题目分析:这个题目有两个做法,我都稍微说一下吧,因为这个题目挂在了网络流的题集里,所以自然得用网络流试试啦。。这是一个经典的二分图匹配问题了,但是限制稍微多了些,对于条件2,我们可以用并查集来处理,要记得实时记录哪些边已经建过了,防止重复建边,对于最后答案的求法,因为答案最小为0,最大为n,所以我们可以二分匹配轮数,也就是判断最后汇点的流量是否等于匹配轮数与人数n之积,这样就能解决这个题了

其实也可以直接用匈牙利跑,毕竟n只有100,每跑一次匈牙利,记得删掉已经匹配的边,跑到不能跑为止就好啦

网络流+二分+并查集:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=210;bool maze[N][N],vis[N][N];int f[N];struct Edge
{int to,w,next;
}edge[N*N];//边数int head[N],cnt,st,ed,n,m,t;void addedge(int u,int v,int w)
{edge[cnt].to=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].to=u;edge[cnt].w=0;//反向边边权设置为0edge[cnt].next=head[v];head[v]=cnt++;
}int d[N],now[N*N];//深度 当前弧优化bool bfs(int s,int t)//寻找增广路
{memset(d,0,sizeof(d));queue<int>q;q.push(s);now[s]=head[s];d[s]=1;while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;if(d[v])continue;if(!w)continue;d[v]=d[u]+1;now[v]=head[v];q.push(v);if(v==t)return true;}}return false;
}int dinic(int x,int t,int flow)//更新答案
{if(x==t)return flow;int rest=flow,i;for(i=now[x];i!=-1&&rest;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;if(w&&d[v]==d[x]+1){int k=dinic(v,t,min(rest,w));if(!k)d[v]=0;edge[i].w-=k;edge[i^1].w+=k;rest-=k;}}now[x]=i;return flow-rest;
}int solve(int st,int ed)
{int ans=0,flow;while(bfs(st,ed))while(flow=dinic(st,ed,inf))ans+=flow;return ans;
}int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);
}void merge(int x,int y)
{int xx=find(x);int yy=find(y);if(xx!=yy)f[xx]=yy;
}void init()//build里初始化:初始化网络流的边
{memcpy(vis,maze,sizeof(maze));memset(head,-1,sizeof(head));cnt=0;
}void Init()//main里初始化:初始化邻接矩阵+并查集
{memset(maze,false,sizeof(maze));for(int i=1;i<N;i++)f[i]=i;st=N-1;ed=N-2;
}void build(int x)
{init();for(int i=1;i<=n;i++){addedge(st,i,x);addedge(i+n,ed,x);}for(int i=1;i<=n;i++)for(int j=1+n;j<=2*n;j++)if(vis[i][j])addedge(i,j,1);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(find(i)==find(j))for(int k=n+1;k<=2*n;k++)if(vis[i][k]&&!vis[j][k]){vis[j][k]=true;addedge(j,k,1);}
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int w;cin>>w;while(w--){Init();scanf("%d%d%d",&n,&m,&t);while(m--){int x,y;scanf("%d%d",&x,&y);maze[x][y+n]=true;}while(t--){int x,y;scanf("%d%d",&x,&y);merge(x,y);}int l=0,r=n,ans;while(l<=r)//二分轮数{int mid=l+r>>1;build(mid);if(solve(st,ed)==mid*n){ans=mid;l=mid+1;}elser=mid-1;}printf("%d\n",ans);}return 0;
}

匈牙利删边:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=110;bool maze[N][N],vis[N];int match[N],f[N],n,m,t;bool dfs(int x)
{for(int i=1;i<=n;i++){if(!vis[i]&&maze[x][i]){vis[i]=true;if(!match[i]||dfs(match[i])){match[i]=x;return true;}}}return false;
}int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);
}void merge(int x,int y)
{int xx=find(x);int yy=find(y);if(xx!=yy)f[xx]=yy;
}void init()
{memset(maze,false,sizeof(maze));for(int i=1;i<N;i++)f[i]=i;
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int w;cin>>w;while(w--){init();scanf("%d%d%d",&n,&m,&t);while(m--){int x,y;scanf("%d%d",&x,&y);maze[x][y]=true;}while(t--){int x,y;scanf("%d%d",&x,&y);merge(x,y);}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(find(i)==find(j))for(int k=1;k<=n;k++)if(maze[i][k])maze[j][k]=true;int ans=0;while(1){memset(match,0,sizeof(match));int cnt=0;for(int i=1;i<=n;i++){memset(vis,false,sizeof(vis));if(dfs(i))cnt++;}if(cnt!=n)break;ans++;for(int i=1;i<=n;i++)//枚举男孩 maze[match[i]][i]=false;//删边 }printf("%d\n",ans);}return 0;
}

HDU - 3081 Marriage Match II(二分+并查集+最大流/匈牙利删边)相关推荐

  1. HDU 3081 Marriage Match II (并查集+二分+最大流 | 并查集+二分图匹配)

    题意:n 个男生.n个女生玩游戏,每个女生都可以和她不讨厌的男生结婚,此外她的朋友如果也不讨厌这个男生,也可以和他结婚:对于女生,如果A和B是朋友,B和C是朋友,那么A和C也是朋友.每次游戏女生会找一 ...

  2. HDU 3081 Marriage Match II【并查集+二分图最大匹配】

    大意:有n个男孩n个女孩,告诉你每个女孩喜欢哪些男孩,又告诉你女孩之间的存在一些朋友关系 一个女孩可以和她喜欢的男孩结婚也可以和她朋友喜欢的男孩结婚, 并且朋友关系可以传递 Once every gi ...

  3. [kuangbin带你飞]专题十一 网络流\N HDU 3081 Marriage Match II

    题目描述 Presumably, you all have known the question of stable marriage match. A girl will choose a boy; ...

  4. HDU - 3081 Marriage Match II 【二分匹配】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意 有n对男女 女生去选男朋友 如果女生从来没和那个男生吵架 那么那个男生就可以当她男朋友 女 ...

  5. HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流...

    题目链接:https://vjudge.net/problem/HDU-3081 Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    ...

  6. hdu3081 Marriage Match II(最大流)

    转载请注明出处: http://www.cnblogs.com/fraud/           --by fraud Marriage Match II Time Limit: 2000/1000 ...

  7. POJ2349二分+并查集,类似最小树的贪心

    题意:       给你n个点,你的任务是构建一颗通讯树,然后给你一个s表示可以选出来s个点两两通讯不花钱,就是费用是0,其他的费用就是两点的距离,有个要求就是其他的费用中最大的那个最小. 思路:   ...

  8. C. Safe Distance(二分 + 并查集)

    C. Safe Distance(二分 + 并查集) 给定一个X×YX \times YX×Y的矩形,里面有n,(1≤n≤1000)n,(1 \leq n \leq 1000)n,(1≤n≤1000) ...

  9. 洛谷P2498 [SDOI2012]拯救小云公主 【二分 + 并查集】

    题目 英雄又即将踏上拯救公主的道路-- 这次的拯救目标是--爱和正义的小云公主. 英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是上千只boss.当英雄意识到自己还是等级1 ...

最新文章

  1. MySQL 存储过程初研究
  2. 插入排序 链表 java_JAVA单链表(多项式)直接插入排序,大家看看我的怎么不行呢...
  3. jsp 跳到servlet路径_想打开一个jsp的页面就跳转到servlet中去,并向servlet传值。用什么跳转...
  4. SQL Server数据归档的解决方案
  5. fnCustomBootTask for local sandbox 在何处赋值
  6. 微信“支付”页全国多地上线“出行服务”,已覆盖108城
  7. Eclipse创建SpringMVC,Spring, Hibernate项目
  8. 各种集合key,value能否为null
  9. 不继承Controller,就不能用fetch()函数
  10. jsp高校学科竞赛管理系统ssh
  11. Xilinx FPGA的Device DNA获取方法
  12. Android home和back事件处理
  13. 前端初学阶段总结与笔记
  14. 百度回应文心一言文生图功能争议
  15. php new object delete,DeleteObject()函数
  16. 【可信计算】第十次课:TPM密码资源管理(二)
  17. Robot framework中支持360浏览器测试
  18. 提到区块链,这一次微软没有再落后
  19. 开源与标准协同发展研究报告(2022)
  20. 7.计算比例工具工具类

热门文章

  1. powerdns mysql_安装PowerDNS(使用MySQL后端)和Poweradmin在Debian Lenny
  2. 基于命令行设置lazy-queue
  3. 静态代理和动态的本质区别
  4. SpringMVC的数据响应-回写数据-返回对象或集合(应用)
  5. SpringMVC的数据响应-页面跳转-返回字符串形式(应用)
  6. JWT令牌创建和解析讲解
  7. Collection集合概述
  8. 用户管理:搭建系统微服务
  9. 注解IOC案例-把自己编写的类使用注解配置
  10. docker里面装mysql_docker中安装及使用mysql