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 }

 

 

 

posted @ 2014-02-13 23:30  水门  阅读(166)  评论(0编辑  收藏  举报