poj 2195 Going Home(最小费用最大流)
题目:http://poj.org/problem?id=2195
有若干个人和若干个房子在一个给定网格中,每人走一个都要一定花费,每个房子只能容纳一人,现要求让所有人进入房子,且总花费最小。
构造一个超级源s和超级汇t,超级源s与U中所有点相连,费用cost[s][u]=0(这是显然的),容量cap[s][u]=1;V中所有点与超级汇t相连,
费用cost[v][t]=0(这是显然的),容量cap[t][v]=1。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <cmath> 9 using namespace std; 10 const int INF=1<<29; 11 const int maxn=210; 12 struct node 13 { 14 int x,y; 15 }p[maxn],h[maxn]; 16 int c[maxn][maxn],f[maxn][maxn],w[maxn][maxn]; 17 int n,m,pn,hn,s,t,ans; 18 bool inq[maxn]; //是否在队列中 19 char str[maxn][maxn]; 20 int pre[maxn],dis[maxn];//上一条弧,Bellman_ford; 21 22 void spfa() 23 { 24 int i,v; 25 queue<int>q; 26 for (i = 0; i < maxn; i++) 27 { 28 dis[i] = INF; 29 pre[i] = -1; 30 inq[i] = false; 31 } 32 q.push(s); 33 inq[s] = true; 34 dis[s] = 0; 35 while (!q.empty()) 36 { 37 int u = q.front(); 38 q.pop(); 39 inq[u] = false; 40 for (v = 0; v <= t; v++) 41 { 42 if (c[u][v]&& dis[v] > dis[u] + w[u][v]) 43 { 44 dis[v] = dis[u] + w[u][v]; 45 pre[v] = u; 46 if (!inq[v]) 47 { 48 q.push(v); 49 inq[v] = true; 50 } 51 } 52 } 53 } 54 } 55 void mcmf() 56 { 57 while (1) 58 { 59 spfa(); 60 if (pre[t] == -1) break; 61 int x = t,minf = INF; 62 while (pre[x] != -1) 63 { 64 minf = min(minf,c[pre[x]][x]); 65 x = pre[x]; 66 } 67 x = t; 68 while (pre[x] != -1) 69 { 70 c[pre[x]][x]-=minf; 71 c[x][pre[x]]+=minf; 72 ans+=minf*w[pre[x]][x]; 73 x = pre[x]; 74 } 75 } 76 } 77 78 int main() 79 { 80 int i,j,pn,hn; 81 while(cin>>n>>m && n || m) 82 { 83 pn = hn = 0; 84 memset(c,0,sizeof(c)); 85 memset(f,0,sizeof(f)); 86 memset(w,0,sizeof(w)); 87 for(i = 0; i < n; i++) 88 { 89 scanf("%s",str[i]); 90 for(j = 0; j < m; j++) 91 { 92 if(str[i][j] == 'H') 93 { 94 h[++hn].x = i; 95 h[hn].y = j; 96 } 97 else if(str[i][j] == 'm') 98 { 99 p[++pn].x = i; 100 p[pn].y = j; 101 } 102 } 103 } 104 s = 0; 105 t = pn + hn + 1; 106 for (i = 1; i <= pn; i++) 107 c[s][i] = 1; 108 for (i = 1; i <= hn; i++) 109 c[i + pn][t] = 1; 110 for (i = 1; i <= pn; i++) 111 { 112 for (j = 1; j <= hn; j++) 113 { 114 c[i][j + pn] = 1; 115 w[i][j + pn] = abs(p[i].x - h[j].x) + abs(p[i].y - h[j].y); 116 w[j + pn][i] = -w[i][j + pn]; 117 } 118 119 } 120 ans = 0; 121 mcmf(); 122 printf("%d\n",ans); 123 } 124 return 0; 125 }