在网上找了一份挺好的模板,先标一下哦~链接君:http://blog.csdn.net/abcjennifer/article/details/5844579

  1. #include <iostream>
  2. #include <string.h>
  3. #include <algorithm>
  4. #include <iostream>
  5. using namespace std;
  6. int max(int a,int b)
  7. {return a<b?b:a;}
  8.  
  9. int min(int a,int b)
  10. {return a<b?a:b;}
  11.  
  12. const int size = ;
  13. const int INF = ;
  14.  
  15. bool map[size][size]; // 二分图的相等子图, map[i][j] = true 代表Xi与Yj有边
  16. bool sx[size], sy[size]; // 标记在一次DFS中,Xi与Yi是否在交错树上
  17. int match[size]; // 保存匹配信息,其中i为Y中的顶点标号,match[i]为X中顶点标号
  18.  
  19. bool DFS(int, const int);
  20. void KM_Perfect_Match(const int n, const int edge[][size])
  21. {
  22. int i, j;
  23. int lx[size], ly[size]; // KM算法中Xi与Yi的标号
  24. for(i = ; i < n; i++)
  25. {
  26. lx[i] = -INF;
  27. ly[i] = ;
  28. for(j = ; j < n; j++)
  29. {
  30. lx[i] = max(lx[i], edge[i][j]);
  31. }
  32. }
  33. bool perfect = false;
  34. while(!perfect)
  35. {
  36. // 初始化邻接矩阵
  37. for(i = ; i < n; i++)
  38. {
  39. for(j = ; j < n; j++)
  40. {
  41. if(lx[i]+ly[j] == edge[i][j])
  42. map[i][j] = true;
  43. else map[i][j] = false;
  44. }
  45. }
  46. // 匹配过程
  47. int live = ;
  48. memset(match, -, sizeof(match));
  49. for(i = ; i < n; i++) {
  50. memset(sx, false, sizeof(sx));
  51. memset(sy, false, sizeof(sy));
  52. if(DFS(i, n)) live++;
  53. else {
  54. sx[i] = true;
  55. break;
  56. }
  57. }
  58. if(live == n) perfect = true;
  59. else {
  60. // 修改标号过程
  61. int ex = INF;
  62. for(i = ; i < n; i++)
  63. {
  64. for(j = ; sx[i] && j < n; j++)
  65. {
  66. if(!sy[j])
  67. ex = min(ex, lx[i]+ly[j]-edge[i][j]);
  68. }
  69. }
  70. for(i = ; i < n; i++)
  71. {
  72. if(sx[i]) lx[i] -= ex;
  73. if(sy[i]) ly[i] += ex;
  74. }
  75. }
  76. }
  77. }
  78.  
  79. bool DFS(int p, const int n)//find augment path from X[p]
  80. {
  81. int i;
  82. for(i = ; i < n; i++)
  83. {
  84. if(!sy[i] && map[p][i])
  85. {
  86. sy[i] = true;
  87. int t = match[i];
  88. match[i] = p;
  89. if(t == - || DFS(t, n))
  90. {
  91. return true;
  92. }
  93. match[i] = t;
  94. if(t != -) sx[t] = true;
  95. }
  96. }
  97. return false;
  98. }
  99.  
  100. int main()
  101. {
  102. int n, edge[size][size]; // edge[i][j]为连接Xi与Yj的边的权值
  103. int i;
  104. int m;
  105. /***************************************************
  106. * record edge[i][j] as edge value between vertex i in X and vertex j in Y
  107. * save n as vertexs need to be match (used in KM_Perfect_Match(n, edge);)
  108. ***************************************************/
  109. int s,d,pow;
  110.  
  111. while(scanf("%d%d",&n,&m)!=EOF)
  112. {
  113. if(n== && m==) break;
  114. memset(edge,,sizeof(edge));
  115. /*最小权: 去掉memset(edge,0,sizeof(edge));改为如下:
  116. for(i=0;i<n;i++)
  117. for(int j=0;j<n;j++)
  118. edge[i][j]=-INF;
  119. */
  120. memset(sx,,sizeof(sx));
  121. memset(sy,,sizeof(sy));
  122. memset(match,,sizeof());
  123. while(m--)
  124. {
  125. scanf("%d%d%d",&s,&d,&pow);
  126. s--;d--;
  127. /*最小权:edge[s][d]=pow; 改为edge[s][d]= - pow;*/
  128. edge[s][d]=pow;
  129. }
  130. KM_Perfect_Match(n, edge);
  131. int cost = ;
  132. for(i=;i<n;i++)
  133. {
  134. cost += edge[match[i]][i];
  135. }
  136. /*最小权:output 改为 -cost*/
  137. cout<<cost<<endl;
  138. }
  139. // cost 为最大匹配的总和, match[]中保存匹配信息
  140. return ;
  141. }

感觉这个模板也不错,比较符合审美。。。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <algorithm>
  5.  
  6. using namespace std;
  7. const int maxn = ;
  8. const int inf = 0x3f3f3f3f;
  9.  
  10. int N, L[maxn], Lx[maxn], Ly[maxn], W[maxn][maxn], slack[maxn];
  11. bool S[maxn], T[maxn];
  12.  
  13. int match (int u) {
  14. S[u] = true;
  15. for (int i = ; i <= N; i++) if (!T[i]) {
  16. if (Lx[u] + Ly[i] == W[u][i]) {
  17. T[i] = true;
  18. if (!L[i] || match(L[i])) {
  19. L[i] = u;
  20. return true;
  21. }
  22. } else
  23. slack[i] = min(slack[i], Lx[u]+Ly[i]-W[u][i]);
  24. }
  25. return false;
  26. }
  27.  
  28. void update () {
  29. int a = inf;
  30. for (int i = ; i <= N; i++) if (!T[i])
  31. a = min(a, slack[i]);
  32.  
  33. for (int i = ; i <= N; i++) {
  34. if (S[i]) Lx[i] -= a;
  35. if (T[i]) Ly[i] += a;
  36. }
  37. }
  38.  
  39. void KM () {
  40. for (int i = ; i <= N; i++) {
  41. L[i] = Lx[i] = Ly[i] = ;
  42. for (int j = ; j <= N; j++)
  43. Lx[i] = max(Lx[i], W[i][j]);
  44. }
  45.  
  46. for (int i = ; i <= N; i++) {
  47. for (int j = ; j <= N; j++) slack[j] = inf;
  48. while (true) {
  49. for (int j = ; j <= N; j++) S[j] = T[j] = false;
  50. if (match(i)) break;
  51. else update();
  52. }
  53. }
  54. }
  55.  
  56. void init () {
  57. for (int i = ; i <= N; i++)
  58. for (int j = ; j <= N; j++)
  59. W[i][j] = -inf;
  60. int u, v;
  61. for (int i = ; i <= N; i++) {
  62. while (scanf("%d", &u) == && u) {
  63. scanf("%d", &v);
  64. W[i][u] = max(W[i][u], -v);
  65. }
  66. }
  67. }
  68.  
  69. int main () {
  70. while (scanf("%d", &N) == && N) {
  71. init();
  72. KM();
  73. bool flag = false;
  74. for (int i = ; i <= N; i++) {
  75. if (L[i] && W[L[i]][i] == -inf)
  76. flag = true;
  77. }
  78.  
  79. if (flag) printf("N\n");
  80. else {
  81. int ans = ;
  82. for (int i = ; i <= N; i++)
  83. ans += (Lx[i] + Ly[i]);
  84. printf("%d\n", -ans);
  85. }
  86. }
  87. return ;
  88. }

二分图最大权最小权完美匹配模板KM的更多相关文章

  1. UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)

    恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图, 把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配. 写的费用流..最大权完美匹配KM算法没看懂 ...

  2. hdu1533 Going Home km算法解决最小权完美匹配

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  3. 紫书 例题11-10 UVa 1349 (二分图最小权完美匹配)

    二分图网络流做法 (1)最大基数匹配.源点到每一个X节点连一条容量为1的弧, 每一个Y节点连一条容量为1的弧, 然后每条有向 边连一条弧, 容量为1, 然后跑一遍最大流即可, 最大流即是最大匹配对数 ...

  4. UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

    题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi  ...

  5. poj3565 Ants km算法求最小权完美匹配,浮点权值

    /** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...

  6. POJ 2404 Jogging Trails(最小权完美匹配)

    [题目链接] http://poj.org/problem?id=2404 [题目大意] 给出一张图,求走遍所有的路径至少一次,并且回到出发点所需要走的最短路程 [题解] 如果图中所有点为偶点,那么一 ...

  7. uva 1411 Ants (权值和最小的完美匹配---KM算法)

    uva 1411 Ants Description Young naturalist Bill studies ants in school. His ants feed on plant-louse ...

  8. [ACM] POJ 3686 The Windy&#39;s (二分图最小权匹配,KM算法,特殊建图)

    The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4158   Accepted: 1777 Descr ...

  9. HDU(1853),最小权匹配,KM

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Other ...

随机推荐

  1. HTTP协议 keep-alive连接 与 BS(firefox-thttpd)实验

    什么是 keep-alive 连接 https://en.wikipedia.org/wiki/HTTP_persistent_connection HTTP persistent connectio ...

  2. 虚拟主机无法使用fsockopen操作处理方法

    一.如何禁用fsockopen()下面是两种常用的禁用fsockopen的方法.1.修改php.ini,将 disable_functions = 后加入 fsockopen2.修改php.ini,将 ...

  3. innodb数据结构

    Jeremy Cole on InnoDB architecture : Efficiently traversing InnoDB B+Trees with the page directory   ...

  4. Team Queue (uva540 队列模拟)

    Team Queue Queues and Priority Queues are data structures which are known to most computer scientist ...

  5. Temporary ASP.NET 拒绝访问

    CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\dd813f66 ...

  6. Intellij IDEA 快捷键介绍

    ctrl-w   使所选表达式逐步增大直到选取整个文件  ctrl+shft+w   逐步减少选中 ctrl-n 可以通过键入类名查找一个类 ctrl-shift-n 可以查找文件 ctrl-e 得到 ...

  7. JAVA-Semaphore信号灯-可实现维护自身线程访问数

    import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Ex ...

  8. Intent 匹配规则

    1.在AndroidManifest.xml中可以为 每个 Activity,Service 设置多个Intent-Filter; 在系统启动和程序安装之后,android会收集AndroidMani ...

  9. 【Nginx】配置Nginx的负载均衡

    参考的优秀文章 tomcat配置文件server.xml详解 AJP协议总结与分析 Using nginx as HTTP load balancer 在本机运行2个Tomcat 现需要运行两个Tom ...

  10. 从零开始学iPhone开发(5)——使用MapKit

    (转)Leonbao:MapKit学习笔记 1.概述插入MapView,设置Delegate(一般为Controller),Annotations记录兴趣位置点(AnnotationView用来显示兴 ...