POJ2195-Going Home
Posted white_hat_hacker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ2195-Going Home相关的知识,希望对你有一定的参考价值。
传送门
题目大意:给定一些人和一些房子,人和房子一样多,求配对。配对代价就是人和房子的距离
思路:这是一个二分图的模型,带权二分图用KM算法即可
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 #define MAXN 105 7 #define pii pair<int,int> 8 #define INF 0x7f7f7f7f 9 using namespace std; 10 int X,Y; 11 int n; 12 int G[MAXN][MAXN]; 13 char s[MAXN][MAXN]; 14 vector<pii> va,vb; 15 int a[MAXN][MAXN]; 16 int b[MAXN][MAXN]; 17 int d[5]={0,1,0,-1,0}; 18 int bfs(int t){ 19 memset(b,0,sizeof(b)); 20 queue<pair<pii,int> > q; 21 q.push(make_pair(va[t-1],0)); 22 b[va[t-1].first][va[t-1].second]=1; 23 while(!q.empty()){ 24 int x=q.front().first.first,y=q.front().first.second; 25 int L=q.front().second; 26 q.pop(); 27 for(int k=0;k<4;k++){ 28 int dx=x+d[k],dy=y+d[k+1]; 29 if(1<=dx&&dx<=X&&1<=dy&&dy<=Y&&!b[dx][dy]){ 30 b[dx][dy]=L+1; 31 q.push(make_pair(make_pair(dx,dy),L+1)); 32 if(a[dx][dy]){ 33 G[t][a[dx][dy]]=-(L+1); 34 } 35 } 36 } 37 } 38 } 39 void init(){ 40 memset(G,0,sizeof(G)); 41 memset(a,0,sizeof(a)); 42 va.clear(); 43 vb.clear(); 44 n=0; 45 for(int i=1;i<=X;i++){ 46 scanf("%s",s[i]+1); 47 for(int j=1;j<=Y;j++){ 48 if(‘m‘==s[i][j]){ 49 va.push_back(make_pair(i,j)); 50 n++; 51 } 52 else if(‘H‘==s[i][j]){ 53 vb.push_back(make_pair(i,j)); 54 a[i][j]=vb.size(); 55 } 56 } 57 } 58 for(int i=1;i<=n;i++){ 59 bfs(i); 60 } 61 } 62 int vis_v1[MAXN],vis_v2[MAXN]; 63 int ex_v1[MAXN],ex_v2[MAXN]; 64 int match[MAXN],slack[MAXN]; 65 int dfs(int x){ 66 vis_v2[x]=1; 67 for(int i=1;i<=n;i++){ 68 if(vis_v1[i]){ 69 continue; 70 } 71 int gap=ex_v1[i]+ex_v2[x]-G[x][i]; 72 if(!gap){ 73 vis_v1[i]=1; 74 if(!match[i]||dfs(match[i])){ 75 match[i]=x; 76 return 1; 77 } 78 } 79 else{ 80 slack[i]=min(slack[i],gap); 81 } 82 } 83 return 0; 84 } 85 int KM(){ 86 memset(match,0,sizeof(match)); 87 memset(ex_v1,0,sizeof(ex_v1)); 88 for(int i=1;i<=n;i++){ 89 ex_v2[i]=G[i][1]; 90 for(int j=2;j<=n;j++){ 91 ex_v2[i]=max(ex_v2[i],G[i][j]); 92 } 93 } 94 for(int i=1;i<=n;i++){ 95 memset(slack,0x7f,sizeof(slack)); 96 while(1){ 97 memset(vis_v1,0,sizeof(vis_v1)); 98 memset(vis_v2,0,sizeof(vis_v2)); 99 100 if(dfs(i)) break; 101 102 int d=INF; 103 for(int j=1;j<=n;j++){ 104 if(!vis_v1[j]){//!!! 105 d=min(d,slack[j]); 106 } 107 } 108 for(int j=1;j<=n;j++){ 109 if(vis_v2[j]){ 110 ex_v2[j]-=d; 111 } 112 if(vis_v1[j]){ 113 ex_v1[j]+=d; 114 } 115 else{ 116 slack[j]-=d; 117 } 118 } 119 } 120 } 121 int ans=0; 122 for(int i=1;i<=n;i++){ 123 ans-=G[match[i]][i]; 124 } 125 return ans; 126 } 127 void solve(){ 128 printf("%d\n",KM()); 129 } 130 int main() 131 { 132 // freopen("data.in","r",stdin); 133 while(1){ 134 scanf("%d%d",&X,&Y); 135 if(!X&&!Y){ 136 break; 137 } 138 init(); 139 solve(); 140 } 141 return 0; 142 }
以上是关于POJ2195-Going Home的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2195 - Going Home - [最小费用最大流][MCMF模板]
POJ 2195 Going Home(KM算法求最小权匹配)