您的位置:首页 > 其它

hdu2813 One fihgt one (KM最小权值和)

2013-09-10 08:38 246 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2813

题解:KM模版题

#include <stdio.h>
#include <string.h>
#include <math.h>
#define INF 0x3f3f3f3f
#define MAXN 201

int w[MAXN][MAXN],match[MAXN];
int lx[MAXN],ly[MAXN],slack[MAXN];
int visitx[MAXN],visity[MAXN];
int nx,ny;
char LvBu[MAXN][21],CaoCao[MAXN][21];

int find(int x)
{
int i,temp;
visitx[x]=1;
for(i=1;i<=ny;++i)
{
if(visity[i])
continue;
temp=lx[x]+ly[i]-w[x][i];
if(temp==0)
{
visity[i]=1;
if(match[i]==-1||find(match[i]))
{
match[i]=x;
return 1;
}
}
else if(slack[i]>temp)
{
slack[i]=temp;
}
}
return 0;
}

int KM()
{
int i,j,d,ans;
memset(ly,0,sizeof(ly));
memset(match,-1,sizeof(match));
for(i=1;i<=nx;++i)
{//lx初始化为与它关联边中最大的
lx[i]=w[i][1];
for(j=2;j<=ny;++j)
if(w[i][j]>lx[i])
lx[i]=w[i][j];
}
for(i=1;i<=nx;++i)
{
for(j=1;j<=ny;++j)
slack[j]=INF;
while(1)
{
memset(visitx,0,sizeof(visitx));
memset(visity,0,sizeof(visity));
if(find(i))
break;
d=INF;
for(j=1;j<=ny;++j)
{
if(!visity[j]&&d>slack[j])
d=slack[j];
}
for(j=1;j<=nx;++j)
{
if(visitx[j])
lx[j]-=d;
}
for(j=1;j<=ny;++j)
{
if(visity[j])
ly[j]+=d;
else
slack[j]-=d;
}
}
}
ans=0;
for(i=1;i<=ny;++i)
{
if(match[i]!=-1)
ans+=w[match[i]][i];
}
return ans;
}

int check(char *s,int flag)
{
int i;
if(flag)
{
for(i=1;i<MAXN;++i)
{
if(strcmp(LvBu[i],s)==0)
return i;
if(strcmp(LvBu[i],"")==0)
{
strcpy(LvBu[i],s);
return i;
}
}
}
else
{
for(i=1;i<MAXN;++i)
{
if(strcmp(CaoCao[i],s)==0)
return i;
if(strcmp(CaoCao[i],"")==0)
{
strcpy(CaoCao[i],s);
return i;
}
}
}
}

int main()
{
int i,j,k,ans,val,x,y;
char str1[21],str2[21];
while(scanf("%d %d %d",&nx,&ny,&k)!=EOF)
{
memset(LvBu,'\0',sizeof(LvBu));
memset(CaoCao,'\0',sizeof(CaoCao));
for(i=1;i<=nx;++i)
{
for(j=1;j<=ny;++j)
w[i][j]=(~INF+1);
}
while(k--)
{
scanf("%s %s %d",str1,str2,&val);
x=check(str1,1);
y=check(str2,0);
w[x][y]=(~val+1);//取反
}
ans=KM();
printf("%d\n",(~ans+1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: