【7.17总结】 匈牙利算法(二分图最大匹配)
二分图就是把图的点集分成X和Y两个集合且连接每条边的两个顶点分别在两个集合。
匹配是指图的边集的一个子集,其中任意两条边没有相同的顶点。
最大匹配就是找到一个匹配使得匹配里面的边数最多。
增广路径就是指从图里面一个还未匹配的点开始,走到一条未匹配边,又经过一条匹配过的边,然后又经过一条未匹配过的边,这样每次交替经过未匹配和匹配的边最后到达一个未匹配的点的一条路径。增广路径有重要的性质:1、增广路一定有奇数条边。 2、增广路中未匹配边一定比匹配边多一条(因为是从未匹配点出发走交错路到未匹配点结束)
由于增广路中未匹配的边比匹配的边多一条,那么把匹配的边和未匹配的边互换一下就会增加一条匹配的边,这就是匈牙利算法的核心思想。
从X集合中找到一个未匹配点,寻找增广路,找到了,匹配数+1,如果没有找到,那么从X中找到下一个未匹配的点,再次寻找增广路,重复上述过程,直到X集合中的所有节点都被“增广”完毕,无论如何都找不到增广路,那么整个图的匹配数就最大了。
代码模板:
1 /* 2 把二分图左右分别集合X和Y,X中有元素n个,Y中有元素m个。 3 每次从X集合中的元素开始寻找增广路,最大匹配就是最后一共有多少条增广路。 4 寻找增广路的过程是个递归的过程,它会一层一层找到底。 5 */ 6 7 int match[MAX][MAX];//match[i][j]=1表示X中的i与Y中的j有连边,match[i][j]=0表示无连边 8 int cx[MAX],cy[MAX];//cx[i]表示与X中i匹配的Y中顶点编号,cy[j]表示与Y中j匹配的x中顶点编号 9 bool vis[MAX];//每次寻找增广路时的访问数组标记,为1表示已经访问过,为0表示没有。 10 11 bool dfs(int u) //如果能够找到一条从u开始的增广路则返回1,否则返回0 12 { 13 for(int v=1;v<=m;v++){ //循环Y中的m个元素v 14 if(!vis[v]&&match[u][v]){ //如果v没有访问过而且与u有连边 15 vis[v]=1; //那么就访问v 16 if(cy[v]==-1||dfs(cy[v])){ //如果还没有与v匹配的边或者有匹配的边但能够从v找到一条增广路 17 cy[v]=u; //那么就把u置为与v匹配的X中的点 18 return 1; //此时找到了增广路,返回true 19 } 20 } 21 } 22 return 0; //循环完了都没找到,返回false 23 } 24 25 26 int main() 27 { 28 int ans=0;//最大匹配数目 29 for(int i=1;i<=n;i++){ //循环X中的n个元素,寻找匹配 30 memset(vis,0,sizeof(vis)); //每次循环都要重置访问标记数组 31 if (dfs(i)) ans++; //增广路数增加 32 } 33 cout<<ans<<endl; //输出最后的结果 34 return 0; 35 }
举个栗子:HDU 2063
题意就是有M个女生,N个男生,过山车只能女生男生配对一起坐,而女生只会挑跟想在一起的男生坐过山车,给出女生的K个条件(选择哪个男生),就总共能有多少对女生男生一起坐过山车。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 using namespace std; 6 const int maxn=505; 7 int match[maxn][maxn]; 8 int cy[maxn]; 9 bool vis[maxn]; 10 int K,N,M; 11 12 bool dfs(int u) 13 { 14 for(int v=1;v<=M;v++){ 15 if(!vis[v]&&match[v][u]){ 16 vis[v]=1; 17 if(cy[v]==-1||dfs(cy[v])){ 18 cy[v]=u; 19 return 1; 20 } 21 } 22 } 23 return 0; 24 } 25 26 27 int main() 28 { 29 while(cin>>K) 30 { 31 if(!K) break; 32 cin>>M>>N; 33 memset(match,0,sizeof(match)); 34 memset(cy,-1,sizeof(cy)); 35 int ans=0,x,y; 36 for(int i=0;i<K;i++){ 37 cin>>x>>y; 38 match[x][y]=1; 39 } 40 for(int i=1;i<=N;i++){ 41 memset(vis,0,sizeof(vis)); 42 if(dfs(i)) ans++; 43 } 44 cout<<ans<<endl; 45 } 46 return 0; 47 }
View Code
转载于:https://www.cnblogs.com/zxhyxiao/p/9324195.html
【7.17总结】 匈牙利算法(二分图最大匹配)相关推荐
- 【模板】匈牙利算法 二分图最大匹配题模板
[任务] 给定一个二分图,用匈牙利算法求这个二分图的最大匹配数. [说明] 求最大匹配,那么我们希望每一个在左边的点都尽量找到右边的一个点和它匹配. 我们一次枚举左边的点x的所有出边指向的点y, 若y ...
- 浅谈匈牙利算法(二分图最大匹配)
前置知识 一张图是二分图,当且仅当它的点可以被分成两部分,而这张图上的所有边的两个端点,都分属不同的部分.我们称这两个点集,一个叫左部,一个叫右部.左部中的点叫左部点:右部中的点叫右部点. 一张图的一 ...
- POJ-3041 匈牙利算法 二分图最大匹配
踢以 给出多个点的坐标 有一种攻击 可以把一次干掉同一列的 或者干掉同一行的 求最少的攻击次数 肥西 由于问题是问选取最少的行和列干掉所有的陨石 可以把输入的r和c看成r和c之间有一条连边因为要实现干 ...
- hdu 4160 Dolls 匈牙利算法求最大匹配
Dolls Time Limit: 2000 ...
- nyoj239 月老的难题 (匈牙利算法,最大匹配,邻接表)
题目239 题目信息 运行结果 本题排行 讨论区 月老的难题 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. ...
- 【HDU - 2444】The Accomodation of Students(二分图判断 + 匈牙利算法求最大匹配)
题干: There are a group of students. Some of them may know each other, while others don't. For example ...
- 染色法判定二分图 匈牙利算法
染色法判定二分图 思路:相邻的点染不同颜色 看能不能染完 如果过程中出现相邻点相同颜色,就不可以 注意:需要遍历n个点 看此点是否被染色过 如果没有就进行一次dfs或bfs 二分图:可以把点分成两个集 ...
- 多目标跟踪之匈牙利算法
0 前言 目标跟踪(Object Tracking)是自动驾驶中非常常见的任务,根据跟踪目标数量的不同,目标跟踪可分为: 单目标跟踪(Single Object Tracking,SOT) 多目标跟踪 ...
- 二分图最大匹配——匈牙利算法
二分图最大匹配 (一).二分图的介绍 1.定义 2.充要条件 (二).二分图的匹配 1.二分图的最大匹配 2.增广路径 3.匈牙利算法 (1).复杂度 (2).算法思路 (3).代码实现 (一).二分 ...
- 二分图匹配--匈牙利算法
文章目录 二分图: 匹配 匈牙利算法 代码: 二分图: 二分图是一个无向图,点集分成子集X和Y,图中每一条边都是一边在X一边在Y 当且仅当无向图G的每一个回路次数都是偶数时(包括0),G就是一个二分图 ...
最新文章
- 【转】文件读写NDK(或Linux)
- mozjpeg:JPEG图片压缩5%,获Facebook支持
- 使用xrandr和cvt命令添加自定义的分辨率模式
- 數據庫ORACLE轉MYSQL存儲過程遇到的坑~(總結)
- 思科模拟服务器怎么写文件,思科模拟服务器配置教程
- 贪心算法两船装载问题Java_贪心算法-最优装载问题
- 深度学习基础知识——信息论(自信息、信息熵与马尔科夫链)
- Java面试全集(中)
- 手机录音ogg格式怎么转换mp3
- 深圳禾正医院自控系统案例|能迪科技canlead中央空调净化系统
- 数据库(表结构)设计技巧及注意事项
- 【渝粤题库】广东开放大学 企业财务报表分析 形成性考核
- 【思维导图】redis详解
- 怎么用计算机批改试卷,试卷弄横线_在电脑上出试卷时答题的横线怎么打_淘题吧...
- Router入门0x205: react-route + redux + react 集成
- 大阪第14天——韩寒同学语录
- 计算机网络(一)——网络编程
- 有时候人们用四位数字表示一个时间,比如 1106 表示 11 点零 6 分。现在,你的程序要根据起始时间和流逝的时间计算出终止时间。 读入两个数字,第一个数字以这样的四位数字表示当前时间,第二个数字
- framework初始化错误,面试大厂应该注意哪些问题?隔壁都馋哭了
- gSOAP 入门实践(一)