二分图匹配
来源:互联网 发布:淘宝助理图片效验出错 编辑:程序博客网 时间:2024/06/11 04:53
入门
KM
KM讲解二,以下有代码分析
#include<bits/stdc++.h>using namespace std;const int maxn = 305;const int INF = 0x3f3f3f3f;int n, nx, ny;//nx,ny分别为x点集y点集的个数int match[maxn], lx[maxn], ly[maxn], slack[maxn]; //lx,ly为顶标,通过修改它们的值来找到最多的匹配,当然从大往小的改,并且lx[i]+ly[j]>=w[i][j]int visx[maxn], visy[maxn], w[maxn][maxn]; //match[j]代表的是y点集的点j与x点集的匹配,初始化为-1,代表没有匹配 //slack[j]代表的是所有与j匹配的x点集的没遍历的点i中lx[i]+ly[y]-w[i][j]尽可能小的值, //这样在Hungary递归中就可以确定:对于每一个y点集的点j,lx[i]+ly[y]-w[i][j]最小的x点集的点iint Hungary(int x){ visx[x] = 1; for(int y = 1; y <= ny; y++) { if(visy[y]) continue; int temp = lx[x]+ly[y]-w[x][y]; if(temp == 0) { visy[y] = 1; if(match[y] == -1 || Hungary(match[y]))//没有匹配的点或者可以通过修改以前匹配好的点来多增加一对 { match[y] = x; return 1; } } else if(slack[y] > temp) ////不在相等子图中slack 取最小的 slack[y] = temp; } return 0;}int KM(){ memset(match, -1, sizeof(match)); memset(ly, 0, sizeof(ly)); for(int i = 1; i <= nx; i++) lx[i] = -INF; for(int i = 1; i <= nx; i++) // //lx初始化为与它关联边中最大的 for(int j = 1; j <= ny; j++) if(w[i][j] > lx[i]) lx[i] = w[i][j]; for(int x = 1; x <= nx; x++) { for(int i = 1; i <= ny; i++) slack[i] = INF; while(1) { memset(visx, 0, sizeof(visx)); memset(visy, 0, sizeof(visy)); if(Hungary(x)) break; ////若成功(找到了增广轨),则该点增广完成,进入下一个点的增广 //若失败(没有找到增广轨),则需要改变一些点的标号,使得图中可行边的数量增加。 //方法为:将所有在增广轨中(就是在增广过程中遍历到)的X方点的标号全部减去一个常数d, //所有在增广轨中的Y方点的标号全部加上一个常数d int d = INF; for(int i = 1; i <= ny; i++) if(!visy[i] && d > slack[i]) d = slack[i]; for(int i = 1; i <= nx; i++)//这部分看我提供的链接 if(visx[i]) lx[i] -= d; for(int i = 1; i <= ny; i++) if(visy[i]) ly[i] += d; else slack[i] -= d;//在链接中的第二种情况中,可能匹配的点的lx[i]+ly[y]-w[i][j]的值要减少d的…… } } int res = 0; for(int i = 1; i <= ny; i++) if(match[i] != -1) res += w[match[i]][i]; return res;}int main(void){ while(cin >> n) { nx = ny = n; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) scanf("%d", &w[i][j]); int ans = KM(); printf("%d\n", ans); } return 0;}
匈牙利算法模板:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N=505; int line[N][N]; int girl[N],used[N]; int k,m,n; bool found(int x) { for(int i=1; i<=n; i++) { if(line[x][i]&&!used[i]) { used[i]=1; if(girl[i]==0||found(girl[i])) { girl[i]=x; return 1; } } } return 0; } int main() { int x,y; while(scanf("%d",&k)&&k) { scanf("%d %d",&m,&n); memset(line,0,sizeof(line)); memset(girl,0,sizeof(girl)); for(int i=0; i<k; i++) { scanf("%d %d",&x,&y); line[x][y]=1; } int sum=0; for(int i=1; i<=m; i++) { memset(used,0,sizeof(used)); if(found(i)) sum++; } printf("%d\n",sum); } return 0; } /*x1 y1x2 y2x3 y3x4 y4x5x6m nfind(i) i是x点集的点girl[i] 就是y点集中的点i在x点集匹配的点的标号,即girl[i]line[i][j] i对应x点集,j对应y点集used[i] 代表y点集的点i是否遍历过*/
阅读全文
0 0
- 二分图图匹配
- 二分图匹配
- 二分图匹配
- 二分图匹配
- 二分图匹配
- 正则二分图匹配
- 二分图匹配
- 二分图匹配总结
- 二分图最大匹配
- 二分图最大匹配 。
- hdu2119二分图匹配
- 二分图匹配
- 二分图匹配
- 二分图匹配算法
- poj3020-二分图匹配
- 二分图匹配
- 二分图最大匹配
- 二分图最大匹配
- 极光推送自动集成与手动集成
- 1.1.4 Broken Necklace
- JDBC和DBCP链接数据库
- Python字符串的encode与decode研究心得——解决乱码问题
- 性能分析工具
- 二分图匹配
- PhpStudy 站点配置流程
- 十一月十三日课堂笔记
- android手把手教你开发launcher(一)(AndroidStudio版)
- 线上环境安装及配置实操(mysql)
- [HNOI2001][luogu1128][bzoj1225] 求正整数
- Android界面进出场动画
- NCMS网络频道云管理系统V3
- Android utc时间