您的位置:首页 > 其它

hdu 2255二分图最大权值匹配的KM 算法

2014-02-06 20:45 411 查看
对KM的深入理解请看以下博客(写的不错的):http://blog.sina.com.cn/s/blog_691ce2b701016reh.html

我的理解:如有错误,请大牛指正!!

1.KM()算法实际就是一种遍历,从权值最大的开始匹配,如果成功的完备匹配了,那这个权值一定是最大的权值。因为我们是从最大的开始一点点小下来遍历的。

2.slack[ ] 这个数组 可以说是一个 松弛变量数组 ,目的是为了 增加匹配。

3.实际也没什么好讲的就是不断的增广,很多也都这样,松弛迫近,跟那什么单纯形法有想通之处。

4. 匈牙利算法进行匹配的寻找。

hdu 2255

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

const int M=400,inf=0x3f3f3f3f;
int w[M][M],link[M],lx[M],ly[M];
int nx,ny,n,slack[M];
int visx[M],visy[M];

int DFS(int x){
visx[x]=1;
int i;
for(i=1;i<=ny;i++){
if(visy[i]) continue;
int t=lx[x]+ly[i]-w[x][i];
if(t==0){
visy[i]=1;
if(link[i]==-1||DFS(link[i])){
link[i]=x;
return 1;
}
}
else if(slack[i]>t) slack[i]=t;
}
return 0;
}

int KM()
{
int i,j;
memset(link,-1,sizeof(link));
memset(ly,0,sizeof(ly));
for(i=1;i<=nx;i++)
for(j=1,lx[i]=-inf;j<=ny;j++){
if(lx[i]<w[i][j]) lx[i]=w[i][j];
}
for(i=1;i<=nx;i++){
for(j=1;j<=ny;j++) slack[j]=inf;
while(1){
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
if(DFS(i)) break;
int d=inf;
for(j=1;j<=ny;j++)
if(!visy[j]&&slack[j]<d)
d=slack[j];
for(j=1;j<=nx;j++)
if(visx[j])
lx[j]-=d;
for(j=1;j<=ny;j++)
if(visy[j])
ly[j]+=d;
else
slack[j]-=d;
}
}
int res=0;
for(i=1;i<=ny;i++){
if(link[i]>-1)
res+=w[link[i]][i];
}
return res;
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF){
nx=ny=n;
for(i=1;i<=nx;i++)
for(j=1;j<=ny;j++)
scanf("%d",&w[i][j]);
printf("%d\n",KM());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: