您的位置:首页 > 编程语言 > Go语言

poj 2195 Going Home

2013-05-12 13:54 295 查看
很裸的二分图最优匹配

把每个‘m’距离其他所有的‘H’之间的权值求出,建立二分图。求出最优匹配。

求最小权值,只需把所有的权值取相反数,求出最大权值,再取相反数。

 

求最优匹配,跟求网络流思想一样,中间有个转换的思想,即有一个反悔的操作,网上资料一大堆呢!

 

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
#define INF 1000000

struct Node
{
int x,y;
};

int g[150][150];
int x[150],y[150];
int visx[150],visy[150];
int link[150];
Node House[150],Man[150];
int nx,ny;
int slack;

int Cost(int i,int j)
{
int x=abs(Man[i].x-House[j].x);
int y=abs(Man[i].y-House[j].y);
return -(x+y);
}

bool dfs(int u)
{
visx[u]=1;
for(int i=0;i<ny;i++)
if( !visy[i] && g[u][i] )
{
int t=x[u]+y[i]-g[u][i];
if(t==0)
{
visy[i]=1;
if( link[i]==-1 || dfs(link[i]) )
{
link[i]=u;
return 1;
}
}
else if(slack>t) slack=t;
}
return 0;
}

int K_M()
{
memset(x,-INF,sizeof(x));
memset(y,0,sizeof(y));
for(int i=0;i<nx;i++)
for(int j=0;j<ny;j++)
if(x[i]<g[i][j])
x[i]=g[i][j];
memset(link,-1,sizeof(link));
for(int i=0;i<nx;i++)
{
while(true)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
slack=INF;
if(dfs(i)) break;
for(int i=0;i<nx;i++)
{
if( visx[i] )
x[i]-=slack;
if( visy[i] )
y[i]+=slack;
}
}
}
int res=0;
for(int i=0;i<nx;i++)
res+=g[link[i]][i];
return res;
}

int main()
{
//	freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d %d",&n,&m)==2 && (n||m) )
{
nx=ny=0;
for(int i=0;i<n;i++)
{
getchar();
for(int j=0;j<m;j++)
{
char c;
scanf("%c",&c);
if(c=='H')
{
House[ny].x=i;
House[ny++].y=j;
}
if(c=='m')
{
Man[nx].x=i;
Man[nx++].y=j;
}
}
}
memset(g,0,sizeof(g));
for(int i=0;i<nx;i++)
for(int j=0;j<ny;j++)
g[i][j]=Cost(i,j);
int ans=K_M();
printf("%d\n",-ans);
}
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 2195