有源汇上下界的最小/大流模板

struct edge {
    int to[Maxm * 2 + 5], Next[Maxm * 2 + 5]; LL val[Maxm * 2 + 5];
    int len, Head[Maxn + 5];
    void Init () { len = 1; memset (Head, 0, sizeof Head); }
    void plus (int x, int y, LL _val) {
        to[++len] = y;
        Next[len] = Head[x];
        val[len] = _val;
        Head[x] = len;
    }
    void add (int x, int y, LL _val) {
        plus (x, y, _val); plus (y, x, 0);
    }
};
struct Node {
    int u, v; LL Below, Up;
    Node () {}
    Node (int _u, int _v, LL _Below, LL _Up) {
        u = _u; v = _v; Below = _Below; Up = _Up;
    }
};
struct Feasible_flow {
    edge mp;
    Node e[Maxm + 5];
    int n, m, s, t, S, T;
    LL d[Maxn + 5];

    bool vis[Maxn + 5];
    int depth[Maxn + 5], cur[Maxn + 5];
    bool BFS () {
        memset (vis, 0, sizeof vis);
        queue <int> q; q.push (s);
        vis[s] = 1; depth[s] = 1; cur[s] = mp.Head[s];
        while (q.size ()) {
            int u = q.front (); q.pop ();
            for (int i = mp.Head[u]; i; i = mp.Next[i]) {
                int v = mp.to[i]; LL w = mp.val[i];
                if (w == 0) continue;
                if (vis[v] == 1) continue;
                vis[v] = 1;
                depth[v] = depth[u] + 1;
                cur[v] = mp.Head[v];
                q.push (v);
                if (v == t) return 1;
            }
        }
        return 0;
    }
    LL Find (int u, LL Limit) {
        if (u == t) return Limit;
        LL flow = 0;
        for (int i = cur[u]; i && flow < Limit; i = mp.Next[i]) {
            cur[u] = i;
            int v = mp.to[i]; LL w = mp.val[i];
            if (w == 0) continue;
            if (depth[v] != depth[u] + 1) continue;
            LL res = Find (v, Min (Limit - flow, w));
            mp.val[i] -= res; mp.val[i ^ 1] += res; flow += res;
        }
        return flow;
    }
    LL Dinic () {
        LL res = 0;
        while (BFS ())
            res += Find (s, Inf);
        return res;
    }
    void forward (int &x) {
        x = mp.Next[x];
    }
    LL solve (int op) {
	    //op == 0,最小流
	    //op == 1,最大流
        mp.Init ();
        memset (d, 0, sizeof d);
        
        for (int i = 1; i <= m; i++) {
            int x, y; LL least, most; x = e[i].u; y = e[i].v; least = e[i].Below; most = e[i].Up;
            mp.add (x, y, most - least);
            d[x] -= least;
            d[y] += least;
        }
        s = 0; t = n + 1; LL sum = 0;
        for (int i = 1; i <= n; i++) {
            if (d[i] < 0) {
                mp.add (i, t, -d[i]);
            }
            if (d[i] > 0) {
                sum += d[i];
                mp.add (s, i, d[i]);
            }
        }
        mp.add (T, S, Inf);
        
        LL temp = Dinic ();
        if (temp != sum) {
            return -1;
        }
        else {
            LL res = mp.val[mp.len];
            forward (mp.Head[S]);
            forward (mp.Head[T]);
            if (op == 0) {
	            s = T; t = S;
	            res -= Dinic ();
			}
			else {
				s = S; t = T;
				res += Dinic ();
			}
            return res;
        }
    }
}G;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值