POJ - 2135 -- Farm Tour (费用流Dijkstra实现)

题目来源:http://poj.org/problem?id=2135

SPFA算法实现:https://blog.csdn.net/moon_sky1999/article/details/81360328

建图的过程中,每条边要存储四次(正向反向的正权边和正向反向的负权边),这样处理出来的图可以看作是不含负权边的图,因此可以使用Dijkstra算法来实现最小费用流。

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxm=1e5+10;
const int maxn=1e4+10;
int n,m;
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];
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 = 1; i <= n; ++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) {
        cnt = 0;
        memset(head, 0, sizeof(head));
        memset(preve, 0, sizeof(preve));
        memset(prevv, 0, sizeof(prevv));
        for (int i = 1; i <= m; ++i) {
            int x, y, z;
            cin >> x >> y >> z;
            ins(x, y, 1, z);
            ins(y, x, 1, z);
        }
        cout << min_cost_flow(1, n, 2) << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/moon_sky1999/article/details/81360017
今日推荐