zoukankan      html  css  js  c++  java
  • POJ 2195 Going Home / HDU 1533(最小费用最大流模板)

    题目大意:

    有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子。每个房子只能进入一个人。

    算法讨论:

    注意是KM 和 MCMF算法,我写的是MCMF算法,一开始想的是连10000个点,但是不会连那些大众点之间的边,只会连超级点和普通点之间的边。后来觉得只要连房子点和

    人点就可以了。连从人到房子的边,容量是1,花费是他们之间的曼哈顿距离,然后超级源点和超级汇点像上面那样连接,注意连点的时候把他们每个点都具体化一下,就是把点值

    都精确到一个连续的范围内去。然后做从超级源点到超级汇点的MCMF算法就可以了。至于那10000个之间的连边,觉得虽然效率不高,但是还是有必要考虑一下。大家有知道的撒

    告诉一下。感谢万分。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <queue>
      7 
      8 using namespace std;
      9 
     10 struct MCMF{
     11     static const int N = 200 * 200 + 5;
     12     static const int M = 200 * 200 * 4 + 100;
     13     static const int oo = 0x3f3f3f3f;
     14     
     15     int n, m, s, t, tot;
     16     int first[N], next[M];
     17     int u[M], v[M], cap[M], flow[M], cost[M];
     18     int dis[N], a[N], inque[N], pre[N];
     19     
     20     void Clear(){memset(first, -1, sizeof first);tot = 0;}
     21     
     22     void Add(int from, int to, int cp, int flw, int ct){
     23         u[tot] = from; v[tot] = to; cap[tot] = cp; flow[tot] = 0; cost[tot] = ct;
     24         next[tot] = first[u[tot]];
     25         first[u[tot]] = tot; ++ tot;
     26         u[tot] = to; v[tot] = from; cap[tot] = 0; flow[tot] = 0; cost[tot] = -ct;
     27         next[tot] = first[u[tot]];
     28         first[u[tot]] = tot; ++ tot;    
     29     }
     30     
     31     bool bfs(int &flw, int &ct){
     32         for(int i = 0; i <= n + 1; ++ i) dis[i] = oo;
     33         memset(inque, 0, sizeof inque);
     34         dis[s] = 0; pre[s] = 0; a[s] = oo; inque[s] = 1;
     35         
     36         queue <int> q;
     37         q.push(s);
     38         while(!q.empty()){
     39             int now = q.front(); q.pop();
     40             inque[now] = 0;
     41             
     42             for(int i = first[now]; i != -1; i = next[i]){
     43                 if(cap[i] > flow[i] && dis[v[i]] > dis[now] + cost[i]){
     44                     dis[v[i]] = dis[now] + cost[i];
     45                     a[v[i]] = min(a[now], cap[i] - flow[i]);
     46                     pre[v[i]] = i;
     47                     if(!inque[v[i]]){
     48                         inque[v[i]] = 1; q.push(v[i]);
     49                     }
     50                 }
     51             }
     52         }
     53         
     54         if(dis[t] == oo) return false;
     55         flw += a[t];
     56         ct += dis[t] * a[t];
     57         
     58         int now = t;
     59         while(now != s){
     60             flow[pre[now]] += a[t];
     61             flow[pre[now]^1] -= a[t];
     62             now = u[pre[now]];
     63         }
     64         return true; 
     65     }
     66     
     67     int MinCostMaxFlow(int s, int t){
     68         this->s = s;this->t = t;
     69         int flw = 0, ct = 0;
     70         while(bfs(flw, ct));
     71         return ct;
     72     }
     73 }Net;
     74 
     75 struct Position{
     76     int l, r, id;
     77     Position(int _l=0, int _r=0, int _id=0): l(_l), r(_r), id(_id){}
     78 }mm[205], HH[205];
     79 
     80 int ns, ms, cnt1, cnt2, tp1, tp2;
     81 char str[105][105];
     82 
     83 void Solve(){
     84         for(int i = 1; i <= tp1; ++ i){
     85             for(int j = 1; j <= tp2; ++ j){
     86                 int x1 = mm[i].l, y1 = mm[i].r;
     87                 int x2 = HH[j].l, y2 = HH[j].r;
     88                 Net.Add(mm[i].id, HH[j].id, 1, 0, abs(x1-x2) + abs(y1-y2));
     89             }
     90         }
     91 }
     92 
     93 int main(){
     94     
     95     while(scanf("%d%d", &ns, &ms) && ns && ms){
     96         Net.Clear();
     97         cnt1 = cnt2 = 0;
     98         tp1 = tp2 = 0;
     99         for(int i = 1; i <= ns; ++ i)
    100             scanf("%s", str[i] + 1);
    101         for(int i = 1; i <= ns; ++ i){
    102             for(int j = 1; j <= ms; ++ j){
    103                 if(str[i][j] == 'm') ++ tp1;
    104                 else if (str[i][j] == 'H') ++ tp2;
    105             }
    106         }
    107         Net.n = tp1 + tp2;
    108         for(int i = 1; i <= ns; ++ i){
    109             for(int j = 1; j <= ms; ++ j){
    110                 if(str[i][j] == 'm'){
    111                     ++ cnt1;
    112                     Net.Add(0, cnt1, 1, 0, 0);
    113                     mm[cnt1] = (Position){i, j, cnt1};
    114                 }
    115             }
    116         }
    117         for(int i = 1; i <= ns; ++ i){
    118             for(int j = 1; j <= ms; ++ j){
    119                 if(str[i][j] == 'H'){
    120                     ++ cnt2;
    121                     Net.Add(tp1 + cnt2, Net.n + 1, 1, 0, 0);
    122                     HH[cnt2] = (Position){i, j, tp1 + cnt2};
    123                 }
    124             }
    125         }
    126         Solve();
    127         printf("%d
    ", Net.MinCostMaxFlow(0, Net.n + 1));
    128     }
    129     
    130     return 0;
    131 }
    POJ 2195/HDU 1533
  • 相关阅读:
    java序列化与反序列化
    HTTP状态码
    基本运算符
    2019.9.10附加题while练习
    2019.9.11作业
    字符串
    列表list
    2019.9.10作业
    数字类型
    数据类型
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5106711.html
Copyright © 2011-2022 走看看