[NOI2008] 志愿者招募

(i) 点表示第 (i)

志愿者 ((s_i,t_i,c_i)),建边 (s_i o t_i +1),费用 (c_i),流量无限

(i)(i+1) 连边 (inf - a[i]),费用为(0)

(S o 1, n+1 o T),费用为 (0),容量 (inf)

#include <bits/stdc++.h>
using namespace std;

#define int long long

namespace mcmf {
const int maxn = 50005;
const int maxm = 300005;
const int inf = 1e+9;
struct R {
    int to, nxt, co, va;
} e[maxm * 2 + 5];
int q[maxm + 5], l, r;
int vs[maxn + 5], nxt[maxn + 5], d[maxn + 5];
int h[maxn + 5], cnt = 1;
int n, m;
int ans;
void add(int u, int v, int w, int c) {
    cnt++;
    e[cnt] = (R){ v, h[u], w, c };
    h[u] = cnt;
    return;
}
int Spfa(int s, int t) {
    for (int i = 1; i <= n; i++) {
        nxt[i] = -1;
        d[i] = inf;
        vs[i] = 0;
    }
    l = r = 1;
    q[l] = s;
    d[s] = 0;
    vs[s] = 1;
    while (l <= r) {
        int u = q[l];
        l++;
        vs[u] = 0;
        for (int i = h[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            int w = e[i].va;
            if (e[i].co && d[u] + w < d[v]) {
                nxt[v] = i;
                d[v] = d[u] + w;
                if (!vs[v]) {
                    q[++r] = v;
                    vs[v] = 1;
                }
            }
        }
    }
    if (d[t] < inf)
        return 1;
    return 0;
}
void Mco(int s, int t) {
    int flow = 0, cost = 0;
    while (Spfa(s, t)) {
        //cout<<"!";
        int mn = inf;
        for (int p = nxt[t]; p != -1; p = nxt[e[p ^ 1].to]) mn = min(e[p].co, mn);
        for (int p = nxt[t]; p != -1; p = nxt[e[p ^ 1].to]) {
            e[p].co -= mn;
            e[p ^ 1].co += mn;
        }
        flow += mn;
        cost += mn * d[t];
        //cout<<"?";
    }
    ans = cost;
    //cout<<flow<<endl;
    return;
}
}

const int N = 50005;
const int inf = 1e+9;

int n,m;

void mk(int u,int v,int w,int c) {
    //cout<<u<<" "<<v<<" "<<w<<" "<<c<<endl;
    mcmf::add(u,v,w,c);
    mcmf::add(v,u,0,-c);
}

int s[N],t[N],c[N],a[N];

signed main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i], mk(i,i+1,inf-a[i],0);
    mcmf::n = n+3;
    mk(n+2,1,inf,0);
    mk(n+1,n+3,inf,0);
    for(int i=1;i<=m;i++) {
        cin>>s[i]>>t[i]>>c[i];
        mk(s[i],t[i]+1,inf,c[i]);
    }
    mcmf::Mco(n+2,n+3);
    cout<<mcmf::ans<<endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/12272064.html