Going Home(MCMF)

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\n",Mincost);
128     }
129     return 0;
130 }
View Code

 

posted @ 2014-02-12 21:36  N_ll  阅读(256)  评论(0编辑  收藏  举报