二分图 最佳匹配 最大权匹配

二分图最佳匹配最大权匹配
whummd 发表于 2006-7-29 16:31:00

转化成一个完美图,用匈牙利算法找增广路实现最大匹配,从而求出最佳匹配,优点是代码量比较少。方便调试。
速度也比较快
算法复杂度为n^3

用pku2195测试了一下时间为0ms

#i nclude<iostream>
using namespace std;
const int maxn=110;
const int maxint=100000000;
int map[maxn][maxn],link[maxn],lx[maxn],ly[maxn];
bool x[maxn],y[maxn];
int n,m;

int find(int v)
{
int j,k;
x[v]=1;
for(j=1;j<=n;j++)
if(y[j]==0&&lx[v]+ly[j]==map[v][j])
{
y[j]=1;
k=link[j];link[j]=v;
if(k==0||find(k))return 1;
link[j]=k;
}
return 0;
}
int main()
{
freopen("a.in","r",stdin);freopen("a.out","w",stdout);
int i,j,k,d,ans;
while(scanf("%d%d",&n,&m)==2)
{
memset(map,0,sizeof(map));
memset(link,0,sizeof(link));
memset(lx,0,sizeof(lx)); memset(ly,0,sizeof(ly));
while(m--){ scanf("%d%d%d",&i,&j,&k); map[i][j]=k;}
//这是最大匹配 最佳匹配就转为负值 map[i][j]=-k;当然输出也是是-ans啦
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(map[i][j]>lx[i])lx[i]=map[i][j];

for(k=1;k<=n;k++)
do{
memset(x,0,sizeof(x));memset(y,0,sizeof(y));
if(find(k))break;
d=maxint;
for(i=1;i<=n;i++)
if(x[i])
for(j=1;j<=n;j++)
if(!y[j]&&lx[i]+ly[j]-map[i][j]<d)
d=lx[i]+ly[j]-map[i][j];
for(i=1;i<=n;i++){if(x[i])lx[i]-=d;if(y[i])ly[i]+=d;}
}while(1);

for(ans=0,i=1;i<=n;i++)ans+=map[link[i]][i];
printf("%d\n",ans);
}

return 0;
}

你可能感兴趣的:(算法,J#)