Loading

连续最短路算法(Successive Shortest Path)(最小费用最大流)

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <vector>
  5 #include <algorithm>
  6 using namespace std;
  7 #define N 205
  8 #define INF 0x3f3f3f3f
  9 struct node {
 10     int x, y;
 11     node () {}
 12     node (int x, int y) : x(x), y(y) {}
 13 };
 14 struct Edge {
 15     int cap, u, v, cost;
 16     Edge() {}
 17     Edge(int u, int v, int cap, int cost) : u(u), v(v), cap(cap), cost(cost) {}
 18 }edge[N*N];
 19 vector<node> p, h;
 20 vector<int> G[N];
 21 int tot, dis[N], inq[N], pre[N], S, T;
 22 
 23 void AddEdge(int u, int v, int cap, int cost) {
 24     edge[tot] = Edge(u, v, cap, cost);
 25     G[u].push_back(tot++);
 26     edge[tot] = Edge(v, u, 0, -cost);
 27     G[v].push_back(tot++);
 28 }
 29 
 30 int CalDis(int x1, int y1, int x2, int y2) {
 31     return abs(x1 - x2) + abs(y1 - y2);
 32 }
 33 
 34 bool SPFA() {
 35     memset(inq, 0, sizeof(inq));
 36     memset(dis, INF, sizeof(dis));
 37     queue<int> que; que.push(S);
 38     dis[S] = 0; inq[S] = 1;
 39     while(!que.empty()) {
 40         int u = que.front(); que.pop(); inq[u] = 0;
 41         for(int i = 0; i < G[u].size(); i++) {
 42             Edge &e = edge[G[u][i]];
 43             if(e.cap > 0 && dis[e.v] > e.cost + dis[u]) {
 44             // 当可以增广并且费用更小的时候
 45                 dis[e.v] = e.cost + dis[u];
 46                 pre[e.v] = G[u][i]; // 记录路径
 47                 if(inq[e.v]) continue;
 48                 que.push(e.v); inq[e.v] = 1;
 49             }
 50         }
 51     }
 52     return dis[T] < INF;
 53 }
 54 
 55 void MFMC(int &mincost, int &maxflow) {
 56     int ans = 0, flow = INF, p;
 57     // 从汇点沿着此次增广的路径往回走,当找到源点的时候退出
 58     for(int u = T; u; u = edge[p].u) {
 59         p = pre[u]; // 找增广的流量
 60         if(edge[p].cap < flow) flow = edge[p].cap;
 61     }
 62     for(int u = T; u; u = edge[p].u) {
 63         p = pre[u];
 64         edge[p].cap -= flow; // 更新每条边的流量
 65         edge[p^1].cap += flow;
 66         ans += flow * edge[p].cost; // 费用 = 单位费用 * 流量
 67     }
 68     mincost += ans, maxflow += flow;
 69 }
 70 
 71 
 72 int main() {
 73     int n, m;
 74     char s[105];
 75     while(scanf("%d%d", &n, &m), n + m) {
 76         p.clear(); h.clear();
 77         for(int i = 0; i < n; i++) {
 78             scanf("%s", s);
 79             for(int j = 0; j < m; j++) {
 80                 if(s[j] == 'H') h.push_back(node(i, j));
 81                 if(s[j] == 'm') p.push_back(node(i, j));
 82             }
 83         }
 84         tot = 0; int sz1 = p.size(), sz2 = h.size();
 85         S = 0, T = sz1 + sz2 + 1;
 86         for(int i = 0; i <= T; i++) G[i].clear();
 87         for(int i = 0; i < sz1; i++) // S到man
 88             AddEdge(S, i + 1, 1, 0);
 89         for(int i = 0; i < sz2; i++) // house到T
 90             AddEdge(i + 1 + sz1, T, 1, 0);
 91         for(int i = 0; i < sz1; i++) {
 92             for(int j = 0; j < sz2; j++) {
 93                 int c = CalDis(p[i].x, p[i].y, h[j].x, h[j].y);
 94                 AddEdge(i + 1, j + 1 + sz1, 1, c);
 95             }
 96         }
 97 
 98         int mincost = 0, maxflow = 0;
 99         while(SPFA()) MFMC(mincost, maxflow);
100         printf("%d\n", mincost);
101     }
102     return 0;
103 }

 

posted @ 2016-12-21 20:13  Shadowdsp  阅读(1584)  评论(0编辑  收藏  举报