KM算法模板
int maxData = 1000000000;
int w[arraysize][arraysize]; //权值
int match[arraysize]; //保存匹配信息,其中i为Y中的顶点标号,match[i]为X中顶点标号
int lx[arraysize],ly[arraysize],slack[arraysize]; //lx[]为左顶点的顶标,ly[]为有顶点的顶标,slack[]记录右顶点的松弛量
bool finalx[arraysize],finaly[arraysize]; // 标记在一次DFS中,Xi与Yi是否在交错树上
int ncount;
bool DFS(int p)
{
int i,j,t;
finalx[p] = true; //将左顶点标记为真
for(i=1;i<=ncount;++i)
{
if(finaly[i]) continue;
int temp = lx[p]+ly[i]-w[p][i];
if(temp==0)
{
finaly[i] = true;
t = match[i];
match[i] = p;
if(t==0 || DFS(t)) return true;
match[i] = t;
}
else if(slack[i]>temp) //检查边(i,j)时,如果它不在相等子图中,则让slack[i]变成原值与A[p]+B[i]-w[p,i]的较小值
{
slack[i] = temp;
}
}
return false;
}
int KM()
{
int i,j;
memset(ly,0,sizeof(ly)); //将右结点的可行顶标的值设置为0
memset(match,0,sizeof(match));
for(i=1;i<=ncount;++i)
{
lx[i]=-maxData;
for(j=1;j<=ncount;++j)
{
if(lx[i]<w[i][j]) //将左顶点的可行顶标的值设置为所有与左顶点关联的边的最大权
lx[i] = w[i][j];
}
}
//从左顶点依次寻找增广路径
for(i=1;i<=ncount;++i)
{
for(j=1;j<=ncount;++j) slack[j] = maxData; //每次寻找增广路径将松弛量函数初始化无穷大
while(1)
{
memset(finalx,0,sizeof(finalx));
memset(finaly,0,sizeof(finaly));
if(DFS(i)) break;
int d = maxData;
for(j=1;j<=ncount;++j) //d应该等于:Min{A[i]+B[j]-w[i,j] | Xi在交错树中,Yi不在交错树中}。
{
if(!finaly[j] && d>slack[j])
d = slack[j];
}
//若未找到完备匹配则修改可行顶标的值
for(j=1;j<=ncount;++j)
{
if(finalx[j]) lx[j]-= d;
if(finaly[j]) ly[j]+= d;
else slack[j] -= d;
}
}
}
int ans= 0; //ans为权值和
for(i=1;i<=ncount;++i)
{
ans -=(lx[i]+ly[i]);
}
return ans;
}