有一份非常好的教程,但是我在百度文库看的,链接如下 力荐!!!!!!!!!
http://wenku.baidu.com/link?url=yKLV9Z1UyA3SCZqcZkDM0miWl5LWLgEJvOh_cY-iPQRIOP23sWg2sNgP_2-is2h_YAJ3yBboNyjyFNG_2N3-uUGbDf13kSgFFQjyOJruK1O
贴个模板,上面我有比较详细的注释
//KM最大最小匹配
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define INF 999999
#define MAX 5110
int n,match[MAX];
//match[v]=u, Y中点v和X中点u匹配,
//同时match[v]==-1说明v还没有访问
bool sx[MAX],sy[MAX];
//sx[i]==true x中的i被匹配过,sy同--用于标记是不是在交错树中
int lx[MAX],ly[MAX],mat[MAX][MAX];
bool path(int u)
{
sx[u]=true;
for(int v=0;v<n;v++)//比匈牙利多了一个构成相等子图的判断
if(!sy[v]&&lx[u]+ly[v]==mat[u][v])
{
sy[v]=true;
if(match[v]==-1||path(match[v]))
{//v还未被匹配或者v匹配了match[v],
//但是可以把match[v]匹配给其他的,那么就把v匹配给u
match[v]=u;
return true;
}
}
return false;
}
//true 是最大匹配 , false是最小匹配, 不错的思想
//没有完美匹配的解,就返回 INF
int KM(bool truth)//可以不用更改地处理最小或最大权匹配
{
int i,j;
if(!truth)//如果是求得最小匹配
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
mat[i][j]=-mat[i][j];
}
//第一步:初始化顶标,lx[i]=max(w[i][j]),ly[i]为零
for(i=0;i<n;i++)
{
lx[i]=-INF;
ly[i]=0;
for(j=0;j<n;j++)
lx[i]=max(lx[i], mat[i][j]);
//if(lx[i]<mat[i][j])
// lx[i]=mat[i][j];
}
memset(match,-1,sizeof(match));
for(int u=0;u<n;u++)
while(1)
{
//匈牙利找完备匹配
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
if(path(u)) break;//某个点找到匹配 进行下一个点
//没有找到匹配,就lx[i]-d,ly[i]+d
//求d,方法:
int dmin=INF;
for(i=0;i<n;i++)
if(sx[i])
for(j=0;j<n;j++)
if(!sy[j])
dmin=min(lx[i]+ly[j]-mat[i][j],dmin);
//修改lx[i]和ly[i],d[i]=min(A[i]+B[j]-w[i][j],i在交错树,y不在交错树)
//这种求法保证了A[i]+B[j]>=w[i][j],并且至少有一条边进入相等子图
//--就是所选的最小的d就等于A[ik]+B[jk]-w[ik][jk],那么A[ik]-=d之后,
//A[ik]+B[jk]-w[ik][jk]==0;就是说至少边(i,j)进入子图
for(i=0;i<n;i++)
{
if(sx[i])
lx[i]-=dmin;
if(sy[i])
ly[i]+=dmin;
}
}
int sum=0;//必要的时候看看这里会不会爆掉
for(j=0;j<n;j++){
if(mat[match[j]][j]==-INF)
return INF;
sum+=mat[match[j]][j];
}
if(!truth)//恢复
{
sum=-sum;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
mat[i][j]=-mat[i][j];
}
return sum;
}
void Map_Init(int m,int n)
{
int x,y,w;
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
mat[i][j]=INF;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&w);
if(mat[x-1][y-1]>w)//处理重边
mat[x-1][y-1]=w;
}
}
int main()
{
int m,i,j,a,b,c;
while(scanf("%d%d",&n,&m)!=EOF)
{
Map_Init(m,n);
int ans=KM(false);
if(ans<INF) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}