LOJ#117 有源汇有上下界最小流

来源:互联网 发布:四氧化三铁化学式算法 编辑:程序博客网 时间:2024/05/22 07:00

题目链接:https://loj.ac/problem/117

解法:

(1)增加超级源点st和超级汇点sd,对于有上下界的边(i,j)流量(L,R)变为R-L,然后i与sd连接容量是L,st与j连接容量是L;网络中规定不能有流量流入st,也不能有流量流入sd;

(2)做一次最大流Dinic;

(3)在汇点t到s连一条容量是inf的边;

(4)在做一次最大流Dinic

(5)当且仅当附加弧都满流是有可行流,最后的最小流是flow[sd->st]^1],st到sd的最大流就是sd到st的最小流;

#include <bits/stdc++.h>using namespace std;typedef long long LL;const LL inf = 1e10;const LL maxn = 70005;const LL maxm = 125005;struct G{    LL v, cap, next, num;    G() {}    G(LL v, LL cap, LL next, LL num) : v(v), cap(cap), next(next), num(num) {}} E[maxm*10];LL p[maxn], T;LL d[maxn], temp_p[maxn], qw[maxn]; //d顶点到源点的距离标号,temp_p当前狐优化,qw队列LL n,m,s,t;void init(){    memset(p, -1, sizeof(p));    T = 0;}void add(LL u, LL v, LL cap, LL num){    E[T] = G(v, cap, p[u], num);    p[u] = T++;    E[T] = G(u, 0, p[v], num);    p[v] = T++;}bool bfs(LL st, LL en, LL n){    LL i, u, v, head, tail;    for(i = 0; i <= n; i++) d[i] = -1;    head = tail = 0;    d[st] = 0;    qw[tail] = st;    while(head <= tail)    {        u = qw[head++];        for(i = p[u]; i + 1; i = E[i].next)        {            v = E[i].v;            if(d[v] == -1 && E[i].cap > 0)            {                d[v] = d[u] + 1;                qw[++tail] = v;            }        }    }    return (d[en] != -1);}LL dfs(LL u, LL en, LL f){    if(u == en || f == 0) return f;    LL flow = 0, temp;    for(; temp_p[u] + 1; temp_p[u] = E[temp_p[u]].next)    {        G& e = E[temp_p[u]];        if(d[u] + 1 == d[e.v])        {            temp = dfs(e.v, en, min(f, e.cap));            if(temp > 0)            {                e.cap -= temp;                E[temp_p[u] ^ 1].cap += temp;                flow += temp;                f -= temp;                if(f == 0)  break;            }        }    }    return flow;}LL dinic(LL st, LL en, LL n){    LL i, ans = 0;    while(bfs(st, en, n))    {        for(i = 0; i <= n; i++) temp_p[i] = p[i];        ans += dfs(st, en, inf);    }    return ans;}LL du[maxn],sum=0, ans=0;int main(){    scanf("%lld%lld%lld%lld",&n,&m,&s,&t);    init();    memset(du,0,sizeof(du));    for(LL i=1; i<=m; i++){        LL u,v,l,r;        scanf("%lld %lld %lld %lld", &u,&v,&l,&r);        add(u,v,r-l, i);        du[u]-=l;        du[v]+=l;    }    LL ss = 0, tt = n+1;    for(LL i=1; i<=n; i++){        if(du[i]>0) sum+=du[i],add(ss,i,du[i], 0);        if(du[i]<0) add(i,tt,-du[i], 0);    }    ans += dinic(ss, tt, n+2);    add(t, s, inf, 0);    ans += dinic(ss, tt, n+2);    if(sum == ans){        printf("%lld\n", E[T-1].cap);    }    else{        puts("please go home to sleep");    }    return 0;}
原创粉丝点击