HDU - 1533 -- Going Home

题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1533

先添加两个点s和t(源点汇点),图中的所有m和H可以看成是点。

建图过程:

1.s与图中所有的m之间建一条流量为1,费用为0的边。

2.图中所有的m与图中所有的H之间建一条流量为1,费用为dis(i,j)的边。dis表示两点之间的距离。

3.图中所有的H与s之间建一条流量为1,费用为0的边。

因此即为求s到t的最小费用流。

Dijkstra算法求最短路的代码:

#include <bits/stdc++.h>
using namespace std;
const int maxm=1e5+10;
const int maxn=1e4+10;
int n,m,tot,ct,hx[maxn],hy[maxn],mx[maxn],my[maxn];
int cnt,head[maxn],h[maxn],dis[maxn],prevv[maxn],preve[maxn];
typedef pair<int,int> P;
struct edge {
    int to, next, cap, cost, rev;
}e[maxm];
int dist(int i,int j) {
    return abs(hx[i] - mx[j]) + abs(hy[i] - my[j]);
}
void ins(int x,int y,int z,int c) {
    e[++cnt].to = y;
    e[cnt].next = head[x];
    head[x] = cnt;
    e[cnt].cap = z;
    e[cnt].rev = cnt + 1;
    e[cnt].cost = c;
    e[++cnt].to = x;
    e[cnt].next = head[y];
    head[y] = cnt;
    e[cnt].cap = 0;
    e[cnt].rev = cnt - 1;
    e[cnt].cost = -c;
}
int min_cost_flow(int s,int t,int f) {
    int ans = 0;
    memset(h, 0, sizeof(h));
    while (f > 0) {
        priority_queue<P, vector<P>, greater<P> > q;
        memset(dis, 63, sizeof(dis));
        dis[s] = 0;
        q.push(P(0, s));
        while (!q.empty()) {
            P p = q.top();
            q.pop();
            int v = p.second;
            if (dis[v] < p.first)continue;
            for (int i = head[v]; i; i = e[i].next) {
                if (e[i].cap > 0 && dis[e[i].to] > dis[v] + e[i].cost + h[v] - h[e[i].to]) {
                    dis[e[i].to] = dis[v] + e[i].cost + h[v] - h[e[i].to];
                    prevv[e[i].to] = v;
                    preve[e[i].to] = i;
                    q.push(P(dis[e[i].to], e[i].to));
                }
            }
        }
        if (dis[t] > 1e8)
            return -1;
        for (int i = 0; i <= 1 + ct + tot; ++i)
            h[i] += dis[i];
        int d = f;
        for (int i = t; i != s; i = prevv[i]) {
            d = min(d, e[preve[i]].cap);
        }
        f -= d;
        ans += d * h[t];
        for (int i = t; i != s; i = prevv[i]) {
            e[preve[i]].cap -= d;
            e[e[preve[i]].rev].cap += d;
        }
    }
    return ans;
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    while (cin >> n >> m) {
        if (n == 0)break;
        memset(head, 0, sizeof(head));
        tot = ct = cnt = 0;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                char c;
                cin >> c;
                if (c == 'H') {
                    hx[++ct] = i;
                    hy[ct] = j;
                }
                if (c == 'm') {
                    mx[++tot] = i;
                    my[tot] = j;
                }
            }
        }
        int s = 0, t = tot + ct + 1;
        for (int i = 1; i <= tot; ++i) {
            ins(s, i, 1, 0);
        }
        for (int i = 1; i <= ct; ++i) {
            ins(tot + i, t, 1, 0);
        }
        for (int i = 1; i <= tot; ++i) {
            for (int j = 1; j <= ct; ++j) {
                ins(i, tot + j, 1, dist(i, j));
            }
        }
        cout << min_cost_flow(s, t, ct) << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/moon_sky1999/article/details/81358099