您的位置:首页 > 其它

km算法模板 hdu2255

2017-10-17 10:44 337 查看
这篇博客讲的很好

http://www.cnblogs.com/wenruo/p/5264235.html

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1100;
const int inf=0x3f3f3f3f;
int g[maxn][maxn];//储存x与y之间的好感度
int lx[maxn],ly[maxn],link[maxn];//lx[]x的期望值,ly[]y的期望值,link[x]x和谁配对。
int slack[maxn];//每一个y提高多少魅力可以与x进行配对
bool vis_x[maxn],vis_y[maxn];//是否被搜过
int nx,ny;
bool dfs(int x)
{
vis_x[x]=true;
for(int y=0;y<ny;y++)
{
if(vis_y[y]) continue;
int tem=lx[x]+ly[y]-g[x][y];//期望值与现实之差。
if(tem==0)//期望值等于现实,看是否可配对
{
vis_y[y]=1;
if(link[y]==-1||dfs(link[y]))//匈牙利算法思想,最大匹配
{
link[y]=x;

4000
return true;
}
}
else if(slack[y]>tem)//不能匹配,看y至少提升多少魅力才可以进行配对
{
slack[y]=tem;
}
}
return false;
}
int km()
{
memset(ly,0,sizeof(ly));
memset(link,-1,sizeof(link));
for(int i=0;i<nx;i++)
{
lx[i]=-inf;
for(int j=0;j<ny;j++)
{
if(lx[i]<g[i][j])
{
lx[i]=g[i][j];//记录x的最大期望值
}
}
}
for(int x=0;x<nx;x++)
{
for(int i=0;i<ny;i++)
{
slack[i]=inf;//初始化
}
while(1)
{
memset(vis_x,false,sizeof(vis_x));
memset(vis_y,false,sizeof(vis_y));
if(dfs(x)) break;//匹配成功,不需要降低期望值
int d=inf;
for(int i=0;i<ny;i++)
{
if(!vis_y[i]&&d>slack[i])//没有被选过,并且魅力值可以少增加点
{
d=slack[i];
}
}
for(int i=0;i<nx;i++)//减少x的期望值
{
if(vis_x[i])
{
lx[i]-=d;
}
}
for(int i=0;i<ny;i++)//相当于下一次如果x降低的期望值大于ly[],则不和其配对
{
if(vis_y[i])
{
ly[i]+=d;
}
else
{
slack[i]-=d;
}
}
}
}
int res=0;
for(int i=0;i<ny;i++)
{
if(link[i]!=-1)
{
res+=g[link[i]][i];
}
}
return res;
}
int main ()
{
int n;
while(~scanf("%d",&n))
{
ny=nx=n;
for(int i=0;i<nx;i++)
{
for(int j=0;j<ny;j++)
{
scanf("%d",&g[i][j]);
}
}
printf("%d\n",km());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: