二分图最大匹配与最小顶点覆盖(教程系列)uva11419——我目前关于最大匹配最清晰的解释。
来源:互联网 发布:mac风扇一直响 编辑:程序博客网 时间:2024/06/04 23:25
定义什么的百度拉拉,我只说证明.
1.假设我们现在已经用匈牙利算法求出了最大匹配,很明显现在已经木有增广路了(即未匹配->匹配->未匹配这些形式的路径,图里是木有的,不过一定要从下面说的那种特殊点开始)
2.现在我们从右边开始标记一些点沿着(未匹配->匹配->未匹配......->匹配)这种形式的路径进行,(特别注意的是这个起点一定没有和匹配边相邻接,为什么?看下面。)
标记路径上经过的所有点。注意起点是右边的点,结束时一定在匹配边结束。
标记完后已经木有从右边的这种点开始的未匹配边了!!!(然后我将证明所有左边已经标记的点和右边未标记的点的数目和,就是最小覆盖也等于最大匹配数)
3.对右边的点分类,标记了的点,和没标记的点,可以发现没标记的点都有和匹配边相连,显然。。。而且没标记的点对应的匹配边的左边那个点也是没标记的。显然。。
对于匹配边也阔以分为两类和右边的没标记的点相邻接,和右边的有标记的部分点相邻接=左边标记了的点数目,匹配边数这样分类时是木有重叠的,所以上述点数目和是最大匹配。
4.然后边又阔以分为两类。两个端点都是标记点,两个端点都是未标记点,嗯很显然等于上面描述的点数目,综上最大匹配数=最小覆盖。
5.最小覆盖<最大匹配是不可能的。。。
6.上述证明一定是正确的,我已经过了uva上的题了,用上面的证明。。。。。。。。。。(关键!!)不过要注意的对于那些度为0的点要排除掉!!!!!!!!!!!!!!!!!!!!!
此题就是把行当成左边点,列是右边点,然后n行m列有点的话让左边n号点连右边m点然后就是求一个最小覆盖。。
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>using namespace std;vector<int>x[1050], y[1050];int visitx[1050], visity[1050], matchy[1050],matchx[1050];int getx[1050], gety[1050];int n, m,point;bool dfs(int num){visitx[num] = 1;for (int i = 0; i < x[num].size(); i++){int to = x[num][i];if (visity[to])continue;//说白了这一步你只能走未匹配边如果visity[to]=1代表走的是匹配边或者i正搜索中你继续走下去阔能有回路visity[to] = 1; //还有就算你visity[to]=1你走后然后后增广你会发现那个y是和两个x相连的。。。if (matchy[to] == -1 || dfs(matchy[to]))//在dfs外面我们是一个一个遍历x的但是当开始dfs后要到x必须走匹配边而且是从y走所以这不用visitx[i]!=1这个条件{matchy[to] = num; matchx[num] = to;return true;}}return false;}int getans(int nn,int mm){int ans = 0;for (int i = 1; i <= nn; i++)matchx[i] = -1;for (int i = 1; i <= mm; i++)matchy[i] = -1;for (int i = 1; i <= nn; i++){for (int j = 1; j <= nn; j++)visitx[j] = 0;for (int j = 1; j <= mm; j++)visity[j] = 0;if (dfs(i))ans++;}return ans;}void mdfs(int num){gety[num] = 1; visity[num] = 1;for (int i = 0; i < y[num].size(); i++){int to = y[num][i];if (visitx[to])continue;//加速需要getx[to] = 1; visitx[to] = 1;mdfs(matchx[to]);}}void mark(int nn, int mm)//每个点最多遍历一次所以是o(n)的{for (int i = 1; i <= nn; i++)getx[i] = 0, visitx[i] = 0;for (int i = 1; i <= mm; i++)gety[i] = 0, visity[i] = 0;for (int i = 1; i <= mm; i++){if (visity[i]||y[i].size()==0)continue;if (matchy[i]==-1)mdfs(i);}}int main(){int k = 1;while (scanf("%d%d%d", &n, &m, &point)&&n&&m&&point){for (int i = 1; i <= n; i++)x[i].clear();for (int i = 1; i <= m; i++)y[i].clear();for (int i = 0; i < point; i++){int a, b;scanf("%d%d", &a, &b);x[a].push_back(b), y[b].push_back(a);}int ans = getans(n,m);mark(n,m);printf("%d", ans);for (int i = 1; i <= n; i++){if (getx[i] == 1)printf(" r%d", i);}for (int i = 1; i <= m; i++){if (gety[i] == 0&&y[i].size()!=0)printf(" c%d", i);}printf("\n");}return 0;}
阅读全文
0 0
- 二分图最大匹配与最小顶点覆盖(教程系列)uva11419——我目前关于最大匹配最清晰的解释。
- uva11419 【最大二分匹配求最小点覆盖 匈牙利算法】
- 二分图:最大独立集&最大匹配&最小顶点覆盖
- POJ3692——Kindergarten (二分图求最小顶点覆盖 (即最大匹配))
- HDU 2063 过山车(匈牙利算法 二分图的最小顶点覆盖 二分图最大匹配)
- HDU 1150 Machine Schedule(匈牙利算法 二分图的最小顶点覆盖 二分图最大匹配)
- 最小顶点数就能覆盖所有边==二分图的最大匹配
- poj3041-Asteroids , 二分图的最小顶点覆盖数 = 最大匹配数
- poj3020_最小覆盖路径(顶点个数-二分图最大匹配数)
- 关于二分图的最大匹配(最小点覆盖)问题的资料整理
- 二分图及其匹配算法——最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配
- DAG最小路径覆盖与二分图最大匹配
- poj3020 匈牙利算法+公式:二分无向图的最小路径覆盖 = 顶点数 - 最大二分匹配数 / 2
- 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配(二分图学习)
- 二分图的最大匹配(最小路径覆盖,最小点覆盖)
- CUGB图论专场2:B - Asteroids 二分图:最小顶点覆盖=最大匹配数
- hdu 1054 Strategic Game 最小顶点覆盖(二分图最大匹配)
- Machine Schedule HDoj (二分图最小顶点覆盖--最大匹配数)
- pyautogui
- jsp页面使用C标签,需要在页面引入c标签库
- Docker学习笔记:Docker 基础用法和命令帮助
- tmp目录文件占用内存分析
- python cart算法的简单实现
- 二分图最大匹配与最小顶点覆盖(教程系列)uva11419——我目前关于最大匹配最清晰的解释。
- linux内存文件系统之指南
- SSM框架集成Redis数据库【Redis·4】
- 记一次JVM调优-跟踪优化二
- (使用字节流实现:FileInputStream和ByteArrayOutputStream)
- 编写Shell脚本的最佳实践
- C# WinForm开发系列
- 身份证实名认证设计、实现思路
- JDBC连接数据库和查询