KM最佳匹配的模板


以下为KM算法模板:


//boj1080 
/*
=================================================*\
| 二分图最佳匹配(kuhn munkras 算法O(m*m*n))
| 邻接距阵形式,复杂度O(m*m*n) 返回最佳匹配值,传入二分图大小n,m
| 邻接距阵map,表示权, match返回一个最佳匹配,未匹配顶点
| match值为-1, 一定注意m<=n,否则循环无法终止,最小权匹配可将权值
| 取相反数

\*==================================================
*/

#include 
<cstdio>
#include 
<memory.h>
const int inf = 0x7fffffff;

int map[25][25],n,lx[25],ly[25],match[25
];
bool x[25],y[25
];

/************* 寻找增广路******************************/

bool SearchPath(int u)
{
     x[u] 
= true;  //x注意标记已匹配 

     for (int v = 1; v <= n; v++)
      
if(!y[v] && ly[v] + lx[u] ==
 map[u][v])
      {
          y[v] 
= true
;
          
if (match[v] == -1 ||
 SearchPath(match[v]))
          {
              match[v] 
=
 u;
              
return true
;
          }
      }
      
return false
;
}

int
 KM()
{
    
int
 i,j,k,d;
    
for (i = 1; i <= n; i++
)
    
while(1
)
    {
        memset(x,
false,sizeof
(x));
        memset(y,
false,sizeof
(y));
        
if (SearchPath(i)) //找到完美匹配子图 

           break;
        d 
=
 inf;
        
for (j = 1; j <= n; j++
)
          
if
 (x[j])
          {
                
for (k = 1; k <= n; k++
)
                 
if (!
y[k])
                    
if (d > lx[j] + ly[k] -
 map[j][k]) 
                       d 
= lx[j] + ly[k] -
 map[j][k];   
          }
        
for (j = 1; j <= n;j ++//降低阶梯 

        {
            
if (x[j])  lx[j] -=
 d;
            
if (y[j])  ly[j] +=
 d;
        }                
    }      
    
int ans = 0
;
    
for (i = 1; i <= n; i++
)
        ans 
+=
 map[match[i]][i];   
    
return
 ans;
}

        
/**********************************************/


int main()
{
    
int
 i,j,k,v;
    
while (scanf("%d",&n) !=
 EOF)
    {
          
for (i = 1; i <= n; i++
)
              
for (j = 1; j <= n; j++
)
              {
                  scanf(
"%d"&
v);
                  map[i][j] 
= -
v;
              }
              
/*
************* 顶标坐标初始化
       ly[i]初始化为0,lx[i]初始化为与i相邻边权最大的值 
     *******************************
*/

          memset(ly,
0,sizeof(ly));
          
for (i = 1; i <= n; i++
)
          {
              lx[i] 
= -
inf;
              
for (j = 1; j <= n; j ++
)
                
if (lx[i] <
 map[i][j])
                   lx[i] 
=
 map[i][j];
          }
          memset(match,
-1,sizeof
(match));
          printf(
"%d\n",-
KM());
/******************************************/


    }
    
return 0;
}

同时BOJ 1084也是一个很裸的求二分图最佳匹配的问题。

你可能感兴趣的:(KM最佳匹配的模板)