• 网络流小结


    @

    有上下界限制网络流建图

    无源汇有上下界可行流

    • 设下界为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;
    }
    
  • 相关阅读:
    微服务治理热门技术揭秘:无损上线
    云原生事件驱动引擎(RocketMQEventBridge)应用场景与技术解析
    阿里云解决方案架构师张平:云原生数字化安全生产的体系建设
    Vue配置对象
    js 实现reduce
    js 实现bind
    Vue简介
    关于Nodejs 技术架构 如何与C++通信
    cdn原理与优缺点 cdn跨域问题
    Vue模板语法 插值语法与指令语法
  • 原文地址:https://www.cnblogs.com/Cwolf9/p/10181669.html
Copyright © 2020-2023  润新知