Poj--2195(最小费用最大流)

2014-12-22 21:10:56

思路:建立总源点,建边到各个男人,然后每个男人建有向边指向每栋房子,每栋房子建边到总汇点。当然每条边容量都为1。建完图就可以搞啦!

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #include <queue>
 10 #include <iostream>
 11 #include <algorithm>
 12 using namespace std;
 13 #define lp (p << 1)
 14 #define rp (p << 1|1)
 15 #define getmid(l,r) (l + (r - l) / 2)
 16 #define MP(a,b) make_pair(a,b)
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const int INF = 1 << 30;
 20 const int maxn = 210;
 21 
 22 int N,M,cntm,cnth,ed;
 23 int mx[maxn],my[maxn];
 24 int hx[maxn],hy[maxn];
 25 int d[maxn][maxn];
 26 int dis[maxn],inq[maxn],pre[maxn];
 27 int first[maxn],edge[maxn],cost[maxn * maxn],cp[maxn * maxn],next[maxn * maxn],ver[maxn * maxn],ecnt;
 28 char g[maxn][maxn];
 29 queue<int> Q;
 30 
 31 void Spfa(){
 32     fill(dis,dis + maxn,INF);
 33     memset(pre,0,sizeof(pre));
 34     memset(inq,0,sizeof(inq));
 35     while(!Q.empty()) Q.pop();
 36     Q.push(0);
 37     inq[0] = 1;
 38     dis[0] = 0;
 39     while(!Q.empty()){
 40         int x = Q.front(); Q.pop();
 41         inq[x] = 0;
 42         for(int i = first[x]; i != -1; i = next[i]){
 43             if(cp[i] == 0) continue;
 44             int v = ver[i];
 45             if(dis[x] + cost[i] < dis[v]){
 46                 dis[v] = dis[x] + cost[i];
 47                 pre[v] = x;
 48                 edge[v] = i;
 49                 if(inq[v] == 0){
 50                     inq[v] = 1;
 51                     Q.push(v);
 52                 }
 53             }
 54         }
 55     }
 56 }
 57 
 58 int MCMF(){
 59     int min_cost = 0;
 60     for(int tt = 1; tt <= cntm; ++tt){
 61         Spfa();
 62         for(int i = ed; i != 0; i = pre[i]){
 63             int id = edge[i];
 64             cp[id] -= 1;
 65             cp[(id & 1) ? id + 1 : id - 1] += 1;
 66         }
 67         min_cost += dis[ed];
 68     }
 69     return min_cost;
 70 }
 71 
 72 void Init(){
 73     memset(d,0,sizeof(d));
 74     memset(first,-1,sizeof(first));
 75     ecnt = 0;
 76 }
 77 
 78 void Add_edge(int u,int v){
 79     next[++ecnt] = first[u];
 80     ver[ecnt] = v;
 81     cp[ecnt] = 1;
 82     cost[ecnt] = d[u][v];
 83     first[u] = ecnt;
 84     
 85     next[++ecnt] = first[v];
 86     ver[ecnt] = u;
 87     cp[ecnt] = 0;
 88     cost[ecnt] = -d[u][v];
 89     first[v] = ecnt;
 90 }
 91 
 92 int main(){
 93     while(scanf("%d%d",&N,&M) != EOF){
 94         if(N == 0 && M == 0) break;
 95         Init();
 96         cntm = cnth = 0;
 97         for(int i = 0; i < N; ++i)
 98             scanf("%s",g[i]);
 99         for(int i = 0; i < N; ++i){    
100             for(int j = 0; j < M; ++j){
101                 if(g[i][j] == 'H'){
102                     ++cnth;
103                     hx[cnth] = i;
104                     hy[cnth] = j;
105                 }
106                 else if(g[i][j] == 'm'){
107                     ++cntm;
108                     mx[cntm] = i;
109                     my[cntm] = j;
110                 }
111             }
112         }
113         ed = cntm + cnth + 1;
114         for(int i = 1; i <= cntm; ++i) Add_edge(0,i);
115         for(int i = 1; i <= cnth; ++i) Add_edge(cntm + i,ed);
116         for(int i = 1; i <= cntm; ++i){
117             for(int j = 1; j <= cnth; ++j){
118                 d[i][cntm + j] = abs(mx[i] - hx[j]) + abs(my[i] - hy[j]);
119                 Add_edge(i,cntm + j);
120             }
121         }
122         printf("%d\n",MCMF());
123     }
124     return 0;
125 }

 

posted @ 2014-12-22 21:12  Naturain  阅读(150)  评论(0编辑  收藏  举报