poj 2195 Going Home

来源:互联网 发布:矩阵1 a 编辑:程序博客网 时间:2024/06/13 04:55

很裸的二分图最优匹配

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

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

 

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

 

#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>using namespace std;#define INF 1000000struct 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;}


 

原创粉丝点击