二分图'最佳匹配' KM算法
Posted pupil-xj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图'最佳匹配' KM算法相关的知识,希望对你有一定的参考价值。
讲得很清楚的博客 推荐! 点我??
附上一模板题 // hdu 2255(求最大权和)
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int INF = 0x3f3f3f3f; 5 const int MAXN = 300+5; 6 7 int n; 8 int w[MAXN][MAXN];// 权值数组 9 int cx[MAXN], cy[MAXN];// "标杆" --核心 10 11 int love[MAXN]; 12 bool visx[MAXN], visy[MAXN]; 13 14 bool dfs(int u) { 15 visx[u] = true; 16 for(int v = 1; v <= n; ++v) { 17 if(!visy[v] && cx[u] + cy[v] == w[u][v]) { 18 visy[v] = true; 19 if(!love[v] || dfs(love[v])) { 20 love[v] = u; 21 return true; 22 } 23 } 24 } 25 return false; 26 } 27 28 int KM() { 29 for(int i = 1; i <= n; ++i) love[i] = 0; 30 for(int i = 1; i <= n; ++i) { 31 while(1) { 32 for(int j = 1; j <= n; ++j) visx[j] = visy[j] = false; 33 if(dfs(i)) break; 34 int d = INF; 35 for(int j = 1; j <= n; ++j) { 36 if(visx[j]) { 37 for(int k = 1; k <= n; ++k) { 38 if(!visy[k]) d = min(d, cx[j]+cy[k]-w[j][k]); 39 } 40 } 41 } 42 for(int i = 1; i <= n; ++i) { 43 if(visx[i]) cx[i] -= d; 44 if(visy[i]) cy[i] += d; 45 } 46 } 47 } 48 int ans = 0; 49 for(int i = 1; i <= n; ++i) { 50 ans += w[love[i]][i]; 51 } 52 return ans; 53 } 54 55 int main() { 56 while(scanf("%d", &n) == 1) { 57 for(int i = 1; i <= n; ++i) { 58 int d = 0; 59 for(int j = 1; j <= n; ++j) { 60 scanf("%d", &w[i][j]); 61 d = max(d, w[i][j]); 62 } 63 cx[i] = d; 64 cy[i] = 0; 65 } 66 printf("%d ", KM()); 67 } 68 return 0; 69 }
// hdu 3488 (最小权值和)
1 #include<cstdio> 2 #include<algorithm> 3 #include<set> 4 using namespace std; 5 const int INF = 0x3f3f3f3f; 6 const int MAXN = 200+5; 7 8 int n, m; 9 int w[MAXN][MAXN]; 10 int cx[MAXN], cy[MAXN]; 11 12 int love[MAXN]; 13 bool visx[MAXN], visy[MAXN]; 14 15 bool dfs(int u) { 16 visx[u] = true; 17 for(int v = 1; v <= n; ++v) { 18 if(!visy[v] && cx[u] + cy[v] == w[u][v]) { 19 visy[v] = true; 20 if(!love[v] || dfs(love[v])) { 21 love[v] = u; 22 return true; 23 } 24 } 25 } 26 return false; 27 } 28 29 int KM() { 30 for(int i = 1; i <= n; ++i) love[i] = 0; 31 for(int i = 1; i <= n; ++i) { 32 while(1) { 33 for(int j = 1; j <= n; ++j) visx[j] = visy[j] = false; 34 if(dfs(i)) break; 35 int b = INF; 36 for(int j = 1; j <= n; ++j) { 37 if(visx[j]) { 38 for(int k = 1; k <= n; ++k) { 39 if(!visy[k]) b = min(b, cx[j] + cy[k] - w[j][k]); 40 } 41 } 42 } 43 for(int j = 1; j <= n; ++j) { 44 if(visx[j]) cx[j] -= b; 45 if(visy[j]) cy[j] += b; 46 } 47 } 48 } 49 int ans = 0; 50 for(int i = 1; i <= n; ++i) { 51 ans += w[love[i]][i]; 52 } 53 return -ans; 54 } 55 56 int main() { 57 int T; 58 scanf("%d", &T); 59 while(T--) { 60 scanf("%d%d", &n, &m); 61 for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) w[i][j] = -INF; 62 int x, y, v; 63 set<int> xx[MAXN]; 64 for(int i = 0; i != m; ++i) { 65 scanf("%d%d%d", &x, &y, &v); 66 if(-v > w[x][y]) w[x][y] = -v, xx[x].insert(v); 67 } 68 for(int i = 1; i <= n; ++i) { 69 cx[i] = -*xx[i].begin(); 70 cy[i] = 0; 71 } 72 printf("%d ", KM()); 73 } 74 return 0; 75 }
以上是关于二分图'最佳匹配' KM算法的主要内容,如果未能解决你的问题,请参考以下文章