KM算法

  1. // S是未匹配的顶点集  
  2. while (M 不是 Mp)  
  3. {  
  4.     //F(S)是Gf中与S中顶点相邻的顶点集  
  5.     if( F(S)==T )  
  6.     {  
  7.         d = min( f[u]+f[w]-weight[u][w] ); //u in S, w not in T  
  8.         for each v in V  
  9.         {  
  10.             if ( v in S )  
  11.                 f[v]=f[v]-d;  
  12.             else  
  13.             if ( v in T )  
  14.                 f[v]=f[v]-d;  
  15.           
  16.         }     
  17.     }  
  18.     else //   
  19.     {  
  20.         w = F(S)-T中一个顶点  
  21.         if ( w未匹配 )  
  22.         {  
  23.             P是刚找到的增大路径  
  24.             M = M与P的对称差分运算结果  
  25.             S是某个未匹配的顶点  
  26.             T= null       
  27.         }  
  28.         else  
  29.         {  
  30.             S=S+ {M中w的相邻点}  
  31.             T=T+w         
  32.         }  
  33.     }  
  34. }  
 

 

最后给一个代码,跟伪代码的思路不是很一样。从网上找的

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <memory.h>  
  3. #include <algorithm>    // 使用其中的 min 函数  
  4. using namespace std;  
  5. const int MAX = 1024;  
  6. int n;                // X 的大小  
  7. int weight [MAX] [MAX];        // X 到 Y 的映射(权重)  
  8. int lx [MAX], ly [MAX];        // 标号  
  9. bool sx [MAX], sy [MAX];    // 是否被搜索过  
  10. int match [MAX];        // Y(i) 与 X(match [i]) 匹配  
  11. // 初始化权重  
  12. void init (int size);  
  13. // 从 X(u) 寻找增广道路,找到则返回 true  
  14. bool path (int u);  
  15. // 参数 maxsum 为 true ,返回最大权匹配,否则最小权匹配  
  16. int bestmatch (bool maxsum = true);  
  17. void init (int size)  
  18. {  
  19.     // 根据实际情况,添加代码以初始化  
  20.     n = size;  
  21.     for (int i = 0; i < n; i ++)  
  22.         for (int j = 0; j < n; j ++)  
  23.             scanf ("%d", &weight [i] [j]);  
  24. }  
  25.   
  26. bool path (int u)  
  27. {  
  28.     sx [u] = true;  
  29.     for (int v = 0; v < n; v ++)  
  30.         if (!sy [v] && lx[u] + ly [v] == weight [u] [v])  
  31.         {  
  32.             sy [v] = true;  
  33.             if (match [v] == -1 || path (match [v]))  
  34.             {  
  35.                 match [v] = u;  
  36.                 return true;  
  37.             }  
  38.         }  
  39.         return false;  
  40. }  
  41. int bestmatch (bool maxsum)  
  42. {  
  43.     int i, j;  
  44.     if (!maxsum)  
  45.     {  
  46.         for (i = 0; i < n; i ++)  
  47.             for (j = 0; j < n; j ++)  
  48.                 weight [i] [j] = -weight [i] [j];  
  49.     }  
  50.     // 初始化标号  
  51.     for (i = 0; i < n; i ++)  
  52.     {  
  53.         lx [i] = -0x1FFFFFFF;  
  54.         ly [i] = 0;  
  55.         for (j = 0; j < n; j ++)  
  56.             if (lx [i] < weight [i] [j])  
  57.                 lx [i] = weight [i] [j];  
  58.     }  
  59.     memset (match, -1, sizeof (match));  
  60.     for (int u = 0; u < n; u ++)  
  61.         while (1)  
  62.         {  
  63.             memset (sx, 0, sizeof (sx));  
  64.             memset (sy, 0, sizeof (sy));  
  65.             if (path (u))  
  66.                 break;  
  67.             // 修改标号  
  68.             int dx = 0x7FFFFFFF;  
  69.             for (i = 0; i < n; i ++)  
  70.                 if (sx [i])  
  71.                     for (j = 0; j < n; j ++)  
  72.                         if(!sy [j])  
  73.                             dx = min (lx[i] + ly [j] - weight [i] [j], dx);  
  74.             for (i = 0; i < n; i ++)  
  75.             {  
  76.                 if (sx [i])  
  77.                     lx [i] -= dx;  
  78.                 if (sy [i])  
  79.                     ly [i] += dx;  
  80.             }  
  81.         }  
  82.     int sum = 0;  
  83.     for (i = 0; i < n; i ++)  
  84.         sum += weight [match [i]] [i];  
  85.     if (!maxsum)  
  86.     {  
  87.         sum = -sum;  
  88.         for (i = 0; i < n; i ++)  
  89.             for (j = 0; j < n; j ++)  
  90.                 weight [i] [j] = -weight [i] [j];         // 如果需要保持 weight [ ] [ ] 原来的值,这里需要将其还原  
  91.     }  
  92.     return sum;  
  93. }  
  94.   
  95. int main()  
  96. {  
  97.     freopen ("in.txt""r", stdin);  
  98.     int n;  
  99.     scanf ("%d", &n);  
  100.     init (n);  
  101.     int cost = bestmatch (true);  
  102.     printf ("%d /n", cost);  
  103.     for (int i = 0; i < n; i ++)  
  104.     {  
  105.         printf ("Y %d -> X %d /n", i, match [i]);  
  106.     }  
  107.     return 0;  
  108. }  
  109. /* 
  110. 5 
  111. 3 4 6 4 9 
  112. 6 4 5 3 8 
  113. 7 5 3 4 2 
  114. 6 3 2 2 5 
  115. 8 4 5 4 7 
  116. //执行bestmatch (true) ,结果为 29 
  117. */  
  118. /* 
  119. 5 
  120. 7 6 4 6 1 
  121. 4 6 5 7 2 
  122. 3 5 7 6 8 
  123. 4 7 8 8 5 
  124. 2 6 5 6 3 
  125. //执行 bestmatch (false) ,结果为 21 
  126. */  
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值