网络流小结

@

有上下界限制网络流建图

无源汇有上下界可行流

  • 设下界为B,上界为C。先让每条边流过B的流量,下界变为0,上界变为C-B。
  • 这样初始流会不满足流量平衡。添加一个附加流(g),满足(sum_{(u,i)in E}[B(u,i)+g(u,i)] = sum_{(i,v)in E}[B(i,v)+g(i,v)])(B+g)是实际流量(f)
  • (M(i)=sum_{(u,i)in E}B(u,i) - sum_{(i,v)in E}B(i,v) = sum_{(i,v)in E}g(i,v) - sum_{(u,i)in E}g(u,i)) = (i)点的流入的下界之和减流出的下界之和
  • (M(i)ge 0:) 我们发现附加流中流出的需要比流入的多(M(i))才可以达到流量平衡,那么这些流从哪来呢。建一个源点SS,建一条从SS到(i)的边,容量为(M(i))
  • (M(i)lt 0:) 我们发现附加流中流入的需要比流出的多(M(i))才可以达到流量平衡,那么这些流从哪来呢。建一个汇点TT,建一条从(i)到TT的边,容量为(M(i))
  • 存在解的条件是:SS流出的边和流入TT的边满流。

115. 无源汇有上下界可行流

const int MXN = 2e3 + 7;
const int MXE = 1e5 + 7;
int n, m;
struct DINIC{
    int tot,vt,vs;
    int d[MXN],head[MXN];
    struct lp{
        int v,w,nex;
    }cw[MXE];
    void add_edge(int a,int b,int c){
        cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
        head[a]=tot;
        cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
        head[b]=tot;
    }
    bool bfs(){
        memset(d,-1,sizeof(d));
        queue<int>Q;
        Q.push(vt);d[vt]=0;
        while(!Q.empty()){
            int u=Q.front();
            Q.pop();
            for(int i=head[u];i!=-1;i=cw[i].nex){
                int v=cw[i].v;
                if(cw[i^1].w&&d[v]==-1){
                    d[v]=d[u]+1;
                    Q.push(v);
                }
            }
        }
        return d[vs]!=-1;
    }
    int dfs(int x,int f){
        if(x==vt||f==0) return f;
        int use=0,w;
        for(int i=head[x];i!=-1;i=cw[i].nex){
            int to=cw[i].v;
            if(d[to]==d[x]-1 && cw[i].w){
                w=dfs(to,min(cw[i].w,f-use));
                cw[i].w-=w,cw[i^1].w+=w;
                use+=w;
                if(use==f) return f;
            }
        }
        //if(!use)d[x]=-1;
        return use;
    }
    void init(int st,int ed){
        tot=-1;
        for(int i = 0; i <= ed; ++i) head[i] = -1;
        vs=st;vt=ed;
    }
    int max_flow(){
        int ans=0;
        while(bfs())ans+=dfs(vs,INF);
        return ans;
    }
}dinic;
int in[MXN], out[MXN], vs, vt, ans[MXE];
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    n = read(), m = read();
    vs = 0, vt = n + 1;
    dinic.init(vs, vt);
    for(int i = 0, a, b, c, d; i < m; ++i) {
        a = read(), b = read(), c = read(), d = read();
        dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
        out[a] += c, in[b] += c;
        ans[i] += c;
    }
    for(int i = 1; i <= n; ++i) {
        if(in[i] >= out[i]) {
            dinic.add_edge(vs, i, in[i] - out[i]);
        }else {
            dinic.add_edge(i, vt, out[i] - in[i]);
        }
    }
    int flow = dinic.max_flow(), flag = (flow != 0);
    for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {
        if(dinic.cw[i].w != 0) flag = 0;
    }
    for(int i = dinic.head[vt]; ~i; i = dinic.cw[i].nex) {
        if(dinic.cw[1^i].w != 0) flag = 0;
    }
    for(int i = 0, j = 0; j < m; ++j, i += 2) {
        ans[j] += dinic.cw[i^1].w;
    }
    if(flag) {
        printf("YES
");
        for(int i = 0; i < m; ++i) printf("%d
", ans[i]);
    }else printf("NO
");
#ifndef ONLINE_JUDGE
    cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
    return 0;
}

116. 有源汇有上下界最大流

方法1:
加TS无穷大边,变成无源汇求可行流,判断是否有解,记录TS边流过的流量,然后删除T->S边和SS与TT所有边及点,求ST最大流,ans = TS边流过的流量+此时最大流
方法2:
加TS无穷大边,变成无源汇求可行流,判断是否有解,删点超源汇(都行),求ST最大流,ans = 最大流

(坑:卡了我的Isap!!!莫名其妙我的Isap跑一次最大流后得到的不是最大流,还得在跑一次,居然还能跑出流量来?除非用一种暴力建图我的Isap才不会出现那个问题。。。

const int MXN = 2e3 + 7;
const int MXE = 1e5 + 7;
int n, m;
struct DINIC{
    int tot,vt,vs;
    int d[MXN],head[MXN];
    struct lp{
        int v,w,nex;
    }cw[MXE];
    void add_edge(int a,int b,int c){
        cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
        head[a]=tot;
        cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
        head[b]=tot;
    }
    bool bfs(){
        memset(d,-1,sizeof(d));
        queue<int>Q;
        Q.push(vt);d[vt]=0;
        while(!Q.empty()){
            int u=Q.front();
            Q.pop();
            for(int i=head[u];i!=-1;i=cw[i].nex){
                int v=cw[i].v;
                if(cw[i^1].w&&d[v]==-1){
                    d[v]=d[u]+1;
                    Q.push(v);
                }
            }
        }
        return d[vs]!=-1;
    }
    int dfs(int x,int f){
        if(x==vt||f==0) return f;
        int use=0,w;
        for(int i=head[x];i!=-1;i=cw[i].nex){
            int to=cw[i].v;
            if(d[to]==d[x]-1 && cw[i].w){
                w=dfs(to,min(cw[i].w,f-use));
                cw[i].w-=w,cw[i^1].w+=w;
                use+=w;
                if(use==f) return f;
            }
        }
        //if(!use)d[x]=-1;
        return use;
    }
    void init(int st,int ed){
        tot=-1;
        for(int i = 0; i <= ed; ++i) head[i] = -1;
        vs=st;vt=ed;
    }
    int max_flow(){
        int ans=0;
        while(bfs())ans+=dfs(vs,INF);
        return ans;
    }
}dinic;
int in[MXN], out[MXN], vs, vt, s, t;
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    n = read(), m = read(), s = read(), t = read();
    vs = 0, vt = n + 1;
    dinic.init(vs, vt);
    int flow = 0, flag, all = 0;

    for(int i = 0, a, b, c, d; i < m; ++i) {
        a = read(), b = read(), c = read(), d = read();
        dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
        out[a] += c, in[b] += c;
    }
    int tmp = dinic.tot + 1;
    for(int i = 1; i <= n; ++i) {
        if(in[i] > out[i]) {
            dinic.add_edge(vs, i, in[i] - out[i]);
            all += in[i] - out[i];
        }else if(in[i] < out[i]){
            dinic.add_edge(i, vt, out[i] - in[i]);
        }
    }
    dinic.add_edge(t, s, INF);

//    for(int i = 0, a, b, c, d; i < m; ++i) {
//        a = read(), b = read(), c = read(), d = read();
//        dinic.addEdge(a, b, d, c);
//        out[a] += c, in[b] += c;
//        all += c;
//    }
//    dinic.addEdge(t, s, INF, 0);

    flow = dinic.max_flow(), flag = (flow != 0);
    for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {//判断是否满流
        if(dinic.cw[i].w != 0) flag = 0;
    }
    for(int i = dinic.head[vt]; ~i; i = dinic.cw[i].nex) {
        if(dinic.cw[1^i].w != 0) flag = 0;
    }
//    flag = (flow == all);
    if(flag) {
        //法1:求可行流,删除T->S边和SS与TT所有边及点,求ST最大流,ans = 可行流+最大流
        flow = dinic.cw[dinic.head[t]^1].w;
        for(int i = tmp; i <= dinic.tot; ++i) {
            dinic.cw[i].v = 0;
        }
        dinic.head[vs] = dinic.head[vt] = -1;
        dinic.vs = s, dinic.vt = t;
        flow += dinic.max_flow();
        //法2:判断可行流,删点(都行),求ST最大流,ans = 最大流
//        dinic.head[vs] = dinic.head[vt] = -1;
//        dinic.vs = s, dinic.vt = t;
//        flow = dinic.max_flow();
        printf("%d
", flow);
    }else printf("please go home to sleep
");
#ifndef ONLINE_JUDGE
    cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
    return 0;
}

暴力建图才能过的Isap

const int MXN = 2e3 + 7;
const int MXE = 1e5 + 7;
int n, m;
struct I_SAP{
    struct lp {
        int v,nex;
        int cap,flow;
    } cw[MXE];
    int NE,NV, vs, vt;
    int head[MXN],pre[MXN],cur[MXN],level[MXN],gap[MXN];
    inline void add_edge(int u,int v,int cap){
        cw[NE].v = v;cw[NE].cap = cap;cw[NE].flow = 0;cw[NE].nex = head[u];
        head[u] = NE++;
        cur[u] = head[u];
        cw[NE].v = u;cw[NE].cap = 0;cw[NE].flow = 0;cw[NE].nex = head[v];
        head[v] = NE++;
        cur[v] = head[v];
    }
    inline void add_edge(int u,int v,int flow, int cap){
        cw[NE].v = v;cw[NE].cap = flow;cw[NE].flow = 0;cw[NE].nex = head[u];
        head[u] = NE++;
        cur[u] = head[u];
    }
    void addEdge(int fro, int too, int val, int lim){
        add_edge(fro, too, val-lim, lim);
        add_edge(too, fro, 0, lim);
        add_edge(vs, too, lim, lim);
        add_edge(too, vs, 0, lim);
        add_edge(fro, vt, lim, lim);
        add_edge(vt, fro, 0, lim);
    }
    inline void bfs(int vt){
        memset(level,-1,sizeof(level));
        memset(gap,0,sizeof(gap));
        level[vt]=0;
        gap[level[vt]]++;
        queue<int>que;
        que.push(vt);
        while(!que.empty()) {
            int u=que.front();
            que.pop();
            for(int i=head[u]; i!=-1; i=cw[i].nex) {
                int v=cw[i].v;
                if(level[v]!=-1)continue;
                level[v]=level[u]+1;
                gap[level[v]]++;
                que.push(v);
            }
        }
    }
    int SAP(int vs,int vt){
        bfs(vt);
        clr(pre, -1);
        for(int i = 0; i <= NV; ++i) pre[i] = -1;
        //for(int i=0;i<=n;++i)cur[i]=head[i];
        int u=pre[vs]=vs,flow=0,aug=INF;
        gap[0]=NV;
        while(level[vs]<NV) {
            bool flag=false;
            for(int &i=cur[u]; i!=-1; i=cw[i].nex) {
                int v=cw[i].v;
                if(cw[i].cap>cw[i].flow&&level[u]==level[v]+1) {
                    flag=true;
                    pre[v]=u;
                    u=v;
                    //  aug=(aug==-1?cw[i].cap:min(aug,cw[i].cap));
                    aug=min(aug,cw[i].cap-cw[i].flow );
                    if(v==vt) {
                        flow+=aug;
                        for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
                            cw[cur[u]].flow+=aug;
                            cw[cur[u]^1].flow-=aug;
                        }
                        //     aug=-1;
                        aug=INF;
                    }
                    break;
                }
            }
            if(flag)continue;
            int minlevel=NV;
            for(int i=head[u]; i!=-1; i=cw[i].nex) {
                int v=cw[i].v;
                if(cw[i].cap>cw[i].flow&&level[v]<minlevel) {
                    minlevel=level[v];
                    cur[u]=i;
                }
            }
            if(--gap[level[u]]==0)break;
            level[u]=minlevel+1;
            gap[level[u]]++;
            u=pre[u];
        }
        return flow;
    }
    void init(int _s, int _t, int all){
        NE = 0; NV = all + 1;
        vs = _s; vt = _t;
        for(int i = 0; i <= NV; ++i) head[i] = cur[i] = -1;
        clr(head, -1), clr(cur, -1);
    }
}dinic;
int in[MXN], out[MXN], vs, vt, s, t;
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    n = read(), m = read(), s = read(), t = read();
    vs = 0, vt = n + 1;
    dinic.init(vs, vt, vt + 1);
    int flow = 0, flag, all = 0;
//    for(int i = 0, a, b, c, d; i < m; ++i) {
//        a = read(), b = read(), c = read(), d = read();
//        dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
//        out[a] += c, in[b] += c;
//        all += c;
//    }
//    for(int i = 1; i <= n; ++i) {
//        if(in[i] >= out[i]) {
//            dinic.add_edge(vs, i, in[i] - out[i]);
//        }else {
//            dinic.add_edge(i, vt, out[i] - in[i]);
//        }
//    }
//    dinic.add_edge(t, s, INF);
    for(int i = 0, a, b, c, d; i < m; ++i) {
        a = read(), b = read(), c = read(), d = read();
        dinic.addEdge(a, b, d, c);
        out[a] += c, in[b] += c;
        all += c;
    }
    dinic.addEdge(t, s, INF, 0);
    flow = dinic.SAP(vs, vt), flag = (flow != 0);
//    debug(flow, all)
    for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {
        if(dinic.cw[i].cap != dinic.cw[i].flow) flag = 0;
    }
    for(int i = dinic.head[vt]; ~i; i = dinic.cw[i].nex) {
        if(dinic.cw[1^i].cap != dinic.cw[1^i].flow) flag = 0;
    }
    flag = (flow >= all);
    if(flag) {
        //法1:求可行流,删除T->S边,求ST最大流,ans = 可行流+最大流
        //法2:判断可行流,删点(都行),求ST最大流,ans = 最大流
        dinic.head[vs] = dinic.head[vt] = -1;
        flow = dinic.SAP(s, t);
        printf("%d
", flow);
    }else printf("please go home to sleep
");
#ifndef ONLINE_JUDGE
    cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
    return 0;
}

117. 有源汇有上下界最小流

做法1:
加TS无穷大边变成无源汇形式求可行流,记录TS无穷大边流量,判断是否有解,删除TS无穷大边(甚至可以把超源汇点及相邻边全删掉),然后残余网络上求TS最大流,ans=TS无穷大边流量 - TS最大流。
做法2:
建超级源汇点求出最大流,连TS无穷大的边,再跑一遍超源汇最大流,判断超级源点出去的边是否满流,TS边流过的流量即为答案。

//法1:
const int MXN = 5e5 + 7;
const int MXE = 4e5 + 7;
int n, m;
struct DINIC {
    int tot, vt, vs, NV;
    int d[MXN], head[MXN], cur[MXN];
    struct lp {
        int v, nex;
        LL w;
    }cw[MXE];
    void add_edge(int a,int b,LL c) {
        cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
        head[a]=tot;
        cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
        head[b]=tot;
    }
    bool bfs() {
        for(int i = 0; i <= NV + 1; ++i) d[i] = -1;
        queue<int>Q;
        Q.push(vt);d[vt]=0;
        while(!Q.empty()) {
            int u=Q.front();
            Q.pop();
            for(int i=head[u];i!=-1;i=cw[i].nex) {
                int v=cw[i].v;
                if(cw[i^1].w&&d[v]==-1){
                    d[v]=d[u]+1;
                    Q.push(v);
                }
            }
        }
        return d[vs]!=-1;
    }
    LL dfs(int x,LL f) {
        if(x==vt||f==0) return f;
        LL use=0,w;
        for(int &i=cur[x];i!=-1;i=cw[i].nex) {
            int to=cw[i].v;
            if(d[to]==d[x]-1 && cw[i].w) {
                w=dfs(to,min(cw[i].w,f-use));
                cw[i].w-=w,cw[i^1].w+=w;
                use+=w;
                if(use==f) return f;
            }
        }
        //if(!use)d[x]=-1;
        return use;
    }
    void init(int st,int ed) {
        tot = -1;
        for(int i = 0; i <= ed + 1; ++i) head[i] = -1;
        vs = st; vt = ed;
    }
    LL max_flow(){
        LL ans = 0;
        while(bfs()) {
            for(int i = 0; i <= NV + 1; ++i) cur[i] = head[i];
            ans+=dfs(vs,INFLL);
        }
        return ans;
    }
}dinic;
LL in[MXN], out[MXN];
int vs, vt, s, t;
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    n = read(), m = read(), s = read(), t = read();
    vs = 0, vt = n + 1;
    dinic.init(vs, vt);
    dinic.NV = vt;
    LL flow = 0, flow2 = 0, flag = 1, all = 0;
    for(LL i = 0, a, b, c, d; i < m; ++i) {
        a = read(), b = read(), c = read(), d = read();
        dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
        out[a] += c, in[b] += c;
    }
    int ret = dinic.tot;
    for(int i = 1; i <= n; ++i) {
        if(in[i] >= out[i]) {
            dinic.add_edge(vs, i, in[i] - out[i]);
            all += in[i] - out[i];
        }else if(in[i] < out[i]){
            dinic.add_edge(i, vt, out[i] - in[i]);
        }
    }
    dinic.add_edge(t, s, INFLL);
    int tmp = dinic.tot;
    dinic.max_flow();
    flow = dinic.cw[dinic.tot].w;
//    for(int i = 0, a, b, c, d; i < m; ++i) {
//        a = read(), b = read(), c = read(), d = read();
//        dinic.addEdge(a, b, d, c);
//        out[a] += c, in[b] += c;
//        all += c;
//    }
//    dinic.addEdge(t, s, INF, 0);
    for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {
        if(dinic.cw[i].w) flag = false;
    }
//    for(int i = tmp; i >= ret + 1; --i) dinic.cw[i].w = dinic.cw[i].v = 0;
//    dinic.head[vs] = -1, dinic.head[vt] = -1;
    dinic.head[t] = dinic.cw[dinic.head[t]].nex;
    dinic.head[s] = dinic.cw[dinic.head[s]].nex;
    dinic.vs = t, dinic.vt = s;
    flow2 = dinic.max_flow();
    if(flag) {
        printf("%lld
", flow - flow2);
    }else printf("please go home to sleep
");
#ifndef ONLINE_JUDGE
    cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
    return 0;
}
//法2:
const int MXN = 5e5 + 7;
const int MXE = 4e5 + 7;
int n, m;
struct DINIC{
    int tot, vt, vs;
    int d[MXN], head[MXN], cur[MXN];
    struct lp{
        int v, nex;
        LL w;
    }cw[MXE];
    void add_edge(int a,int b,LL c){
        cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
        head[a]=tot;
        cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
        head[b]=tot;
    }
    bool bfs(){
        for(int i = 0; i <= vt + 1; ++i) d[i] = -1;
        queue<int>Q;
        Q.push(vt);d[vt]=0;
        while(!Q.empty()){
            int u=Q.front();
            Q.pop();
            for(int i=head[u];i!=-1;i=cw[i].nex){
                int v=cw[i].v;
                if(cw[i^1].w&&d[v]==-1){
                    d[v]=d[u]+1;
                    Q.push(v);
                }
            }
        }
        return d[vs]!=-1;
    }
    LL dfs(int x,LL f){
        if(x==vt||f==0) return f;
        LL use=0,w;
        for(int &i=cur[x];i!=-1;i=cw[i].nex){
            int to=cw[i].v;
            if(d[to]==d[x]-1 && cw[i].w){
                w=dfs(to,min(cw[i].w,f-use));
                cw[i].w-=w,cw[i^1].w+=w;
                use+=w;
                if(use==f) return f;
            }
        }
        //if(!use)d[x]=-1;
        return use;
    }
    void init(int st,int ed){
        tot=-1;
        for(int i = 0; i <= ed; ++i) head[i] = -1;
        vs=st;vt=ed;
    }
    LL max_flow(){
        LL ans=0;
        while(bfs()) {
            for(int i = vs; i <= vt; ++i) cur[i] = head[i];
            ans+=dfs(vs,INFLL);
        }
        return ans;
    }
}dinic;
LL in[MXN], out[MXN];
int vs, vt, s, t;
int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
    n = read(), m = read(), s = read(), t = read();
    vs = 0, vt = n + 1;
    dinic.init(vs, vt);
    LL flow = 0, flow2 = 0, flag = 1, all = 0;
    for(LL i = 0, a, b, c, d; i < m; ++i) {
        a = read(), b = read(), c = read(), d = read();
        dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
        out[a] += c, in[b] += c;
    }
    for(int i = 1; i <= n; ++i) {
        if(in[i] > out[i]) {
            dinic.add_edge(vs, i, in[i] - out[i]);
            all += in[i] - out[i];
        }else if(in[i] < out[i]){
            dinic.add_edge(i, vt, out[i] - in[i]);
        }
    }
    flow = dinic.max_flow();
    dinic.add_edge(t, s, INFLL);
//    for(int i = 0, a, b, c, d; i < m; ++i) {
//        a = read(), b = read(), c = read(), d = read();
//        dinic.addEdge(a, b, d, c);
//        out[a] += c, in[b] += c;
//        all += c;
//    }
//    dinic.addEdge(t, s, INF, 0);
    flow2 = dinic.max_flow();
    for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {
        if(dinic.cw[i].w) flag = false;
    }
    if(flag) {
        assert(flow2 == dinic.cw[dinic.head[t]^1].w);
        printf("%lld
", dinic.cw[dinic.head[t]^1].w);
    }else printf("please go home to sleep
");
#ifndef ONLINE_JUDGE
    cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
    return 0;
}

板子题:洛谷P3376

I_SAP

struct I_SAP{
    struct lp {
        int v,nex;
        int cap,flow;
    } cw[MXE];
    int NE,NV, vs, vt;
    int head[MXN],pre[MXN],cur[MXN],level[MXN],gap[MXN];
    inline void add_edge(int u,int v,int cap){
        cw[NE].v = v;cw[NE].cap = cap;cw[NE].flow = 0;cw[NE].nex = head[u];
        head[u] = NE++;
        cur[u] = head[u];
        cw[NE].v = u;cw[NE].cap = 0;cw[NE].flow = 0;cw[NE].nex = head[v];
        head[v] = NE++;
        cur[v] = head[v];
    }
    inline void bfs(int vt){
        memset(level,-1,sizeof(level));
        memset(gap,0,sizeof(gap));
        level[vt]=0;
        gap[level[vt]]++;
        queue<int>que;
        que.push(vt);
        while(!que.empty()) {
            int u=que.front();
            que.pop();
            for(int i=head[u]; i!=-1; i=cw[i].nex) {
                int v=cw[i].v;
                if(level[v]!=-1)continue;
                level[v]=level[u]+1;
                gap[level[v]]++;
                que.push(v);
            }
        }
    }
    int SAP(int vs,int vt){
        bfs(vt);
        memset(pre,-1,sizeof(pre));
        //for(int i=0;i<=n;++i)cur[i]=head[i];
        int u=pre[vs]=vs,flow=0,aug=INF;
        gap[0]=NV;
        while(level[vs]<NV) {
            bool flag=false;
            for(int &i=cur[u]; i!=-1; i=cw[i].nex) {
                int v=cw[i].v;
                if(cw[i].cap>cw[i].flow&&level[u]==level[v]+1) {
                    flag=true;
                    pre[v]=u;
                    u=v;
                    //  aug=(aug==-1?cw[i].cap:min(aug,cw[i].cap));
                    aug=min(aug,cw[i].cap-cw[i].flow );
                    if(v==vt) {
                        flow+=aug;
                        for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
                            cw[cur[u]].flow+=aug;
                            cw[cur[u]^1].flow-=aug;
                        }
                        //     aug=-1;
                        aug=INF;
                    }
                    break;
                }
            }
            if(flag)continue;
            int minlevel=NV;
            for(int i=head[u]; i!=-1; i=cw[i].nex) {
                int v=cw[i].v;
                if(cw[i].cap>cw[i].flow&&level[v]<minlevel) {
                    minlevel=level[v];
                    cur[u]=i;
                }
            }
            if(--gap[level[u]]==0)break;
            level[u]=minlevel+1;
            gap[level[u]]++;
            u=pre[u];
        }
        return flow;
    }
    void init(int _s, int _t, int all){
        NE = 0; NV = all + 1;
        vs = _s; vt = _t;
        for(int i = 0; i <= NV; ++i) head[i] = cur[i] = -1;
    }
}sap;

DINIC1

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<bitset>
#define mme(a,b) memset((a),(b),sizeof((a)))
#define precision(x,d) cout<<fixed<<setprecision(d)<<x<<"
"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;

const int INF = 0x3f3f3f3f;
const int MXN = 1e4+7;
const int MXE = 4e5+7;
int vs, vt;
struct DINIC{
  int tot,vt,vs;
  int d[MXN],head[MXN];
  struct lp{
    int v,w,nex;
  }cw[MXE];
  void add_edge(int a,int b,int c){
    cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
    head[a]=tot;
    cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
    head[b]=tot;
  }
  bool bfs(){
    memset(d,-1,sizeof(d));
    queue<int>Q;
    Q.push(vt);d[vt]=0;
    while(!Q.empty()){
      int u=Q.front();
      Q.pop();
      for(int i=head[u];i!=-1;i=cw[i].nex){
        int v=cw[i].v;
        if(cw[i^1].w&&d[v]==-1){
          d[v]=d[u]+1;
          Q.push(v);
        }
      }
    }
    return d[vs]!=-1;
  }
  /*int dfs(int x,int low){
    if(x==vt||low==0)return low;
    int flow=0,used=0;
    for(int i=head[x];i!=-1;i=cw[i].nex){
      int v=cw[i].to;
      if(cw[i].w&&d[v]+1==d[x]&&(used=dfs(v,min(low,cw[i].w)))>0){
        //used=dfs(v,min(low,cw[i].w));
        if(!used)continue;
        flow+=used,low-=used;
        cw[i].w-=used;cw[i^1].w+=used;
        if(!low)break;
      }
    }
    if(!flow)d[x]=-1;
    return flow;
  }*/
  int dfs(int x,int f){
    if(x==vt||f==0) return f;
    int use=0,w;
    for(int i=head[x];i!=-1;i=cw[i].nex){
      int to=cw[i].v;
      if(d[to]==d[x]-1 && cw[i].w){
        w=dfs(to,min(cw[i].w,f-use));
        cw[i].w-=w,cw[i^1].w+=w;
        use+=w;
        if(use==f) return f;
      }
    }
    if(!use)d[x]=-1;
    return use;
  }
  void init(int st,int ed){
    tot=-1;
    memset(head,-1,sizeof(head));
    vs=st;vt=ed;
  }
  int max_flow(){
    int ans=0;
    while(bfs())ans+=dfs(vs,INF);
    return ans;
  }
}dinic;


int main(){
    int u,v,w,n,m;
    scanf("%d%d%d%d",&n,&m,&vs,&vt);
    dinic.init(vs,vt);
    for(int i=1; i<=m; i++) {
        scanf("%d%d%d",&u,&v,&w);
        dinic.add_edge(u,v,w);
    }
    printf("%d
",dinic.max_flow());
    return 0;
}

Isap

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = 0x3fffffff;
template <int N, int M>
struct Isap{
    int top;
    int d[N], pre[N], cur[N], gap[N];
    struct Vertex {
        int head;
    } V[N];
    struct Edge {
        int v, next;
        int c, f;
    } E[M];
    void init() {
        memset(V, -1, sizeof(V));
        top = 0;
    }
    void add_edge(int u, int v, int c) {
        E[top].v = v;
        E[top].c = c;
        E[top].f = 0;
        E[top].next = V[u].head;
        V[u].head = top++;
    }
    void add(int u, int v, int c) {
        add_edge(u, v, c);
        add_edge(v, u, 0);
    }
    void set_d(int t) {
        queue<int> Q;
        memset(d, -1, sizeof(d));
        memset(gap, 0, sizeof(gap));
        d[t] = 0;
        Q.push(t);
        while (!Q.empty()) {
            int v = Q.front(); Q.pop();
            ++gap[d[v]];
            for (int i = V[v].head; ~i; i = E[i].next) {
                int u = E[i].v;
                if (d[u] == -1) {
                    d[u] = d[v] + 1;
                    Q.push(u);
                }
            }
        }
    }
    int sap(int s, int t, int num) {
        set_d(t);
        int ans = 0, u = s;
        int flow = inf;
        memcpy(cur, V, sizeof(V));
        while (d[s] < num) {
            int &i = cur[u];
            for (; ~i; i = E[i].next) {
                int v = E[i].v;
                if (E[i].c > E[i].f && d[u] == d[v] + 1) {
                    u = v;
                    pre[v] = i;
                    flow = min(flow, E[i].c - E[i].f);
                    if (u == t) {
                        while (u != s) {
                            int j = pre[u];
                            E[j].f += flow;
                            E[j ^ 1].f -= flow;
                            u = E[j ^ 1].v;
                        }
                        ans += flow;
                        flow = inf;
                    }
                    break;
                }
            }
            if (i == -1) {
                if (--gap[d[u]] == 0)
                    break;
                int dmin = num - 1;
                cur[u] = V[u].head;
                for (int j = V[u].head; ~j; j = E[j].next)
                    if (E[j].c > E[j].f)
                        dmin = min(dmin, d[E[j].v]);
                d[u] = dmin + 1;
                ++gap[d[u]];
                if (u != s)
                    u = E[pre[u] ^ 1].v;
            }
        }
        return ans;
    }
};
Isap<200005, 400005> Sap;
int tux[100001], tuy[100001],st,zt;
int main(){
    int n, m;
    scanf("%d%d%d%d", &n, &m, &st, &zt);
    int q, w, e;
    Sap.init();
    for (int a = 1; a <= m; a++){
        scanf("%d%d%d", &q, &w, &e);
        Sap.add(q, w, e);
    }
    printf("%d
",Sap.sap(st, zt, 9 * m + 2));
    return 0;
}
原文地址:https://www.cnblogs.com/Cwolf9/p/10181669.html