http://poj.org/problem?id=2195
题意:在一个n*m的图中,'m'代表人,'H'代表房子,人每移动一次的费用为1,求所有人移动到房子里的最小花费。
思路:最小费用最大流问题。关键是建图,建好图后就是MCMF的模板题了。。
关于建图:增加一个原点S,一个汇点T, S与所有人相连,容量为1,花费为0;每个人与所有房子相连,容量为1,花费为|人与房子的水平距离|+|人与房子的垂直距离|;最后所有的房子 与汇点相连,容量为1,花费为0。
关于算法:多次spfa找增广路,然后求最大流。最小花费+=原点到汇点的最小距离*每次增光后的最大流量
1 #include <stdio.h> 2 #include <iostream> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <string.h> 6 #include <queue> 7 using namespace std; 8 9 const int N=505; 10 const int INF=1<<28; 11 struct node 12 { 13 int x,y; 14 } m[N],h[N]; 15 int cap[N][N],cost[N][N]; 16 int pre[N],vis[N],dis[N]; 17 int cntm,cnth,t; 18 19 int spfa() 20 { 21 queue<int>q; 22 for (int i = 0; i <= t; i++) 23 { 24 dis[i] = INF; 25 vis[i] = 0; 26 pre[i] = -1; 27 } 28 dis[0]=0; 29 q.push(0); 30 vis[0] = 1; 31 while(!q.empty()) 32 { 33 int u = q.front(); 34 vis[u] = 0; 35 q.pop(); 36 for (int i = 0; i <= t; i++) 37 { 38 if (cap[u][i]&&dis[i]>dis[u]+cost[u][i]) 39 { 40 pre[i] = u; 41 dis[i] = dis[u]+cost[u][i]; 42 if (!vis[i]) 43 { 44 q.push(i); 45 vis[i] = 1; 46 } 47 } 48 } 49 } 50 if (dis[t]==INF) 51 return 0; 52 return 1; 53 } 54 int MCMF() 55 { 56 int Maxflow = INF; 57 int Mincost = 0; 58 while(spfa()) 59 { 60 int u = t; 61 while(pre[u]!=-1) 62 { 63 Maxflow = min(Maxflow,cap[pre[u]][u]); 64 u = pre[u]; 65 } 66 Mincost += dis[t]*Maxflow; 67 u = t; 68 while(pre[u]!=-1) 69 { 70 cap[pre[u]][u]-=Maxflow; 71 cap[u][pre[u]]+=Maxflow; 72 u = pre[u]; 73 } 74 } 75 return Mincost; 76 } 77 void build() 78 { 79 for (int i = 1; i <= cntm; i++) 80 { 81 for (int j = 1; j <= cnth; j++) 82 { 83 cap[i][j+cntm] = 1; 84 cost[i][j+cntm] = abs(m[i].x-h[j].x)+abs(m[i].y-h[j].y); 85 cost[j+cntm][i] = -cost[i][j+cntm]; 86 } 87 } 88 for (int i = 1; i <= cntm; i ++) 89 { 90 cap[0][i] = 1; 91 cost[0][i] = 0; 92 cap[i+cntm][t] = 1; 93 cost[i+cntm][t] = 0; 94 } 95 } 96 int main() 97 { 98 int row,col; 99 while(~scanf("%d%d",&row,&col)) 100 { 101 if (row==0&&col==0) 102 break; 103 char ch; 104 cntm = 0,cnth = 0; 105 memset(cap,0,sizeof(cap)); 106 memset(cost,0,sizeof(cost)); 107 for (int i = 1; i <= row; i++) 108 { 109 for (int j = 1; j <= col; j++) 110 { 111 cin>>ch; 112 if (ch=='m') 113 { 114 m[++cntm].x = i; 115 m[cntm].y = j; 116 } 117 if (ch=='H') 118 { 119 h[++cnth].x = i; 120 h[cnth].y = j; 121 } 122 } 123 } 124 t = cnth+cntm+1; 125 build(); 126 int Mincost = MCMF(); 127 printf("%d ",Mincost); 128 } 129 return 0; 130 }