费用流模板

const int Maxn = 1e4;
const int Maxm = 1e5;
const int Maxq = 1e7;
const LL Limit = 1e14; 
const LL Inf = 0x3f3f3f3f3f3f3f;

struct Date {
    int x, y; LL flux, val;
    
    Date () {}
    Date (int _x, int _y, LL _flux, LL _val) {
        x = _x; y = _y; flux = _flux; val = _val;
    }
};
struct edge {
    int to[Maxm * 2 + 5], Next[Maxm * 2 + 5]; LL flux[Maxm * 2 + 5], val[Maxm * 2 + 5];
    int len, Head[Maxn + 5];

    edge () { len = 1; memset (Head, 0, sizeof Head); }
    void Init () { len = 1; memset (Head, 0, sizeof Head); }
    void plus (int x, int y, LL _flux, LL _val) {
        to[++len] = y;
        flux[len] = _flux;
        val[len] = _val;
        Next[len] = Head[x];
        Head[x] = len;
    }
    void add (int x, int y, LL _flux, LL _val) {
        plus (x, y, _flux, _val);
        plus (y, x, 0, -_val);
    }
    void rev_add (int x, int y, LL _flux, LL _val) {
        plus (x, y, 0, _val);
        plus (y, x, _flux, -_val);
    }
};
struct Max_Flow {
    edge mp;
    Date e[Maxm + 5];
    int n, m, s, t;

    void add (int x, int y, LL _flux, LL _val) {
        e[++m] = Date (x, y, _flux, _val);
    }

    bool vis[Maxn + 5];
    int hh, tt, q[Maxq + 5];
    LL dist[Maxn + 5]; int fa[Maxn + 5];
    void Init () {
        mp.Init ();
        hh = 1; tt = 0;
        n = m = s = t = 0;
        memset (vis, 0, sizeof vis);
        memset (dist, 0x3f, sizeof dist);
    }
    bool Spfa () {
        memset (vis, 0, sizeof vis);
        memset (dist, 0x3f, sizeof dist);
        hh = 1; tt = 0; q[++tt] = s; dist[s] = 0;
        
        while (hh <= tt) {
            int u = q[hh++];
            vis[u] = 0;

            for (int i = mp.Head[u]; i; i = mp.Next[i]) {
                int v = mp.to[i]; LL flux = mp.flux[i], w = mp.val[i];
                if (flux == 0) continue;
                if (dist[u] + w < dist[v]) {
                    dist[v] = dist[u] + w;
                    fa[v] = i;
                    if (!vis[v]) {
                        q[++tt] = v;
                        vis[v] = 1;
                    }
                }
            }
        }
        return dist[t] <= Limit;
    }
    LL Update () {
        int p = t; LL cost = 0, flow = Inf;
        while (p != s) {
            cost += mp.val[fa[p]];
            flow = Min (flow, mp.flux[fa[p]]);
            p = mp.to[fa[p] ^ 1];
        }
        p = t;
        while (p != s) {
            mp.flux[fa[p]] -= flow;
            mp.flux[fa[p] ^ 1] += flow;
            p = mp.to[fa[p] ^ 1];
        }
        return cost * flow;
    }
    void Build_Positive () {
        mp.Init ();
        rep (i, 1, m)
            mp.add (e[i].x, e[i].y, e[i].flux, e[i].val);
    }
    LL Cost_Positive () {
        Build_Positive ();
        LL res = 0;
        while (Spfa ()) {
            res += Update ();
        }
        return res;
    }

    int depth[Maxn + 5], cur[Maxn + 5];
    bool BFS () {
        memset (depth, 0, sizeof depth);
        hh = 1; tt = 0; q[++tt] = s;
        depth[s] = 1; cur[s] = mp.Head[s];
        while (hh <= tt) {
            int u = q[hh++];
            for (int i = mp.Head[u]; i; i = mp.Next[i]) {
                int v = mp.to[i]; LL flux = mp.flux[i];
                if (flux == 0) continue;
                if (depth[v]) continue;
                depth[v] = depth[u] + 1;
                cur[v] = mp.Head[v];
                q[++tt] = v;
                if (v == t) return 1;
            }
        }
        return 0;
    }
    LL DFS (int u, LL Up) {
        if (u == t) return Up;
        if (Up == 0) return 0;
        LL flow = 0;
        while (cur[u] && flow < Up) {
            int i = cur[u]; cur[u] = mp.Next[cur[u]];
            int v = mp.to[i]; LL flux = mp.flux[i];
            if (flux == 0) continue;
            if (depth[v] != depth[u] + 1) continue;
            LL tmp = DFS (v, Min (Up - flow, flux));
            if (tmp == 0) depth[v] = -1;
            flow += tmp; mp.flux[i] -= tmp; mp.flux[i ^ 1] += tmp;
            if (mp.flux[i] && flow >= Up) cur[u] = i;
        }
        return flow;
    }
    LL Dinic () {
        Build_Positive ();
        LL flow = 0;
        while (BFS ()) {
            flow += DFS (s, Inf);
        }
        return flow;
    }
    
    LL h[Maxn + 5];
    void Spfa_For_Dijkstra () {
        memset (vis, 0, sizeof vis);
        memset (dist, 0x3f, sizeof dist);
        hh = 1; tt = 0; q[++tt] = s; dist[s] = 0;
        
        while (hh <= tt) {
            int u = q[hh++];
            vis[u] = 0;

            for (int i = mp.Head[u]; i; i = mp.Next[i]) {
                int v = mp.to[i]; LL flux = mp.flux[i], w = mp.val[i];
                if (flux == 0) continue;
                if (dist[u] + w < dist[v]) {
                    dist[v] = dist[u] + w;
                    fa[v] = i;
                    if (!vis[v]) {
                        q[++tt] = v;
                        vis[v] = 1;
                    }
                }
            }
        }
        
        rep (i, 1, n)
            if (h[i] + dist[i] < Limit)
                h[i] += dist[i];
    }
    bool Dijkstra () {
        memset (vis, 0, sizeof vis);
        memset (dist, 0x3f, sizeof dist);
        priority_queue <PII, vector <PII>, greater <PII> > p; 
        p.push (MP (0, s)); dist[s] = 0;
        while (p.size ()) {
            PII tmp = p.top (); p.pop ();
            int u = tmp.se;
            if (vis[u]) continue; vis[u] = 1;
            for (int i = mp.Head[u]; i; i = mp.Next[i]) {
                int v = mp.to[i]; LL flux = mp.flux[i], w = mp.val[i] + h[u] - h[v];
                if (flux == 0) continue;
                if (vis[v]) continue;
                if (dist[u] + w < dist[v]) {
                    dist[v] = dist[u] + w;
                    fa[v] = i;
                    p.push (MP (dist[v], v));
                }
            }
        }
        
        rep (i, 1, n)
            if (h[i] + dist[i] < Limit)
                h[i] += dist[i];
        return dist[t] <= Limit;
    }
    LL Cost_Positive_Dijkstra () {
        Build_Positive ();
        Spfa_For_Dijkstra ();
        LL res = 0;
        while (Dijkstra ()) {
            res += Update ();
        }
        return res;
    }

    int S, T;
    LL d[Maxn + 5];
    LL Build_Negative () {
        mp.Init (); S = s; T = t; s = Maxn - 2; t = Maxn - 1;
        LL res = 0;
        rep (i, 1, m) {
            if (e[i].val < 0) {
                mp.rev_add (e[i].x, e[i].y, e[i].flux, e[i].val);
                res += e[i].flux * e[i].val;
                d[e[i].y] += e[i].flux;
                d[e[i].x] -= e[i].flux;
            }
            else mp.add (e[i].x, e[i].y, e[i].flux, e[i].val);
        }
        rep (i, 1, n)
            if (d[i] > 0) mp.add (s, i, d[i], 0);
            else if (d[i] < 0) mp.add (i, t, -d[i], 0);
        
        while (Spfa ()) {
            res += Update ();
        }
        return res; 
    }
    LL Cost_Negative () {
        LL flow = Build_Negative ();
        s = S; t = T;
        while (Spfa ()) {
            flow += Update ();
        }
        return flow;
    }
}G;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值