The 15-th BIT Campus H. Treasure Hunt(最大费用可行流)

题意:

给定一个带费用的流量网络,要求最大费用(不要求最大流)。

思路:

最小费用最大流魔改,将插入边的费用取反,此时每次进行增广会选一条最短的路径对答案产生贡献,开始这个路径是负的,但是之后为了满足最大流,贡献可能变成正的,因此只要对cost不断取min,最后的mincost就是答案的相反数。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e3+5;
const ll INF=2e17;
typedef pair<ll,ll> pii;
struct MCMF {
    struct Edge {
        ll v, cap, cost, rev;
    };

    ll flow, cost, s, t, n,ans=INF;
    ll dist[MAXN], H[MAXN], pv[MAXN], pe[MAXN];
    std::vector<Edge> G[MAXN];

    bool dijkstra() {
        std::priority_queue<pii, std::vector<pii>, std::greater<pii> > q;
        std::fill(dist, dist + n + 1, INF);
        dist[s] = 0; q.push({0, s});
        while (!q.empty()) {
            pii x = q.top(); q.pop();
            ll &u = x.second;
            if (dist[u] < x.first) continue;
            for (ll i = 0; i < G[u].size(); ++i) {
                Edge &e = G[u][i];
                ll &v = e.v;
                pii y(dist[u] + e.cost + H[u] - H[v], v);
                if (e.cap > 0 && dist[v] > y.first) {
                    dist[v] = y.first;
                    pe[v] = i, pv[v] = u;
                    q.push(y);
                }
            }
        }

        if (dist[t] == INF) return false;
        for (ll i = 0; i <= n; ++i) H[i] += dist[i];

        ll f = INF;
        for (ll v = t; v != s; v = pv[v]) f = std::min(f, G[pv[v]][pe[v]].cap);

        flow += f;
        cost += f * H[t];
        ans=min(ans,cost);

        for (ll v = t; v != s; v = pv[v]) {
            Edge &e = G[pv[v]][pe[v]];
            e.cap -= f;
            G[v][e.rev].cap += f;
        }
        return true;
    }

    void solve(ll s, ll t) {
        this->s = s, this->t = t;
        flow = cost = 0;
        std::fill(H, H + n + 1, 0);
        while (dijkstra());
    }

    void init(ll n) {
        this->n = n;
        for (ll i = 0; i <= n; ++i) G[i].clear();
    }

    void addEdge(ll u, ll v, ll cap, ll cost) {
        G[u].push_back({v, cap, cost, G[v].size()});
        G[v].push_back({u, 0, -cost, G[u].size() - 1});
    }

} mcmf;
int a[MAXN];
int main () {
    int n,m;
    scanf("%d%d",&n,&m);
    int s=n+1,t=n+2;
    mcmf.init(n+2);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=m;i++){
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        mcmf.addEdge(u,v,c,-a[u]);
    }
    mcmf.addEdge(s,1,INF,0);
    mcmf.addEdge(n,t,INF,-a[n]);
    mcmf.solve(s,t);
    printf("%lld\n",-mcmf.ans);
}
posted @ 2021-02-14 20:54  UCPRER  阅读(65)  评论(0编辑  收藏  举报