zoukankan      html  css  js  c++  java
  • 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
    ",-mcmf.ans);
    }
    
  • 相关阅读:
    javascript中keyCode与charCode属性
    handlebars.js基础学习笔记
    ajax个人学习笔记
    ajax三级联动
    background-position 用法详细介绍
    js学习笔记
    CSS浮动(float,clear)通俗讲解
    linux常用命令(个人学习笔记)
    MySQL函数
    String s = new String(“abc”); 可能产生几个对象?
  • 原文地址:https://www.cnblogs.com/ucprer/p/14402671.html
Copyright © 2011-2022 走看看