View Code
工作人员集合M和工作N是二分图的两个部分,工作人员i对工作j的满意度k作为边<i,j>的权值,要求一个令所有工作人员
满意度最大的匹配就是求这个二分图的带权最大匹配。这里用到KM算法,由于不是很懂KM算法,所以要感谢
http://www.cnblogs.com/north_dragon/archive/2010/06/03/1750789.html

这位大牛的模板。在一年中最较特殊的2月的最后一天抓住AC的机会。

#include
<iostream>
#include
<cstring>
#include
<cstdio>

using namespace std;
const int maxData = 1000000000;
const int arraysize = 110;
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;
}


int main()
{
int i,j;

while(scanf("%d",&ncount) && ncount)
{
memset(w,
0,sizeof(w));

for(i = 1;i <= ncount;++i)
{
for(j = 1;j <= ncount;++j)
{
scanf(
"%d",&w[i][j]);
// w[j][i] = w[i][j];
}
}

printf(
"%d\n",-KM());
}

return 0;
}
posted on 2011-02-28 23:26  c++fans  阅读(376)  评论(0编辑  收藏  举报