• 上下界网络流总结


    参考:

    [1] : https://blog.csdn.net/corsica6/article/details/81488993

    [2] : https://www.luogu.com.cn/problemnew/solution/P4553

    说明

    1. 可行流:一个网络网络中,存在一条流,满足任意点的总流入量等于总流出量(即流量守恒)。
    2. 边的流量:网络流连边时连的反向边上的flowflowflow值,即为该边流量。(考虑在流过这条边时,在正向边上减去了流量大小的值,而反向边上恰好加上了这个值)。

    无源汇上下界可行流

    给定 (n) 个点, (m) 条边的网络,求一个可行解,使得边 ((u,v)) 的流量介于 ([B(u,v),C(u,v)]) 之间,并且整个网络满足流量守恒。

    设:(inB[u] = sum B(i,u), outB[u] = sum B(u,i), d[u] = inB[u] - outB[u])

    新建源汇,S' 向 d>0 的点连边,d<0 的点向 T‘ 连边,容量为相应的d。

    在该网络上求最大流,则每条边的流量+下界就是原网络的一个可行流。

    有源汇上下界可行流

    从T到S连一条下界为0,上届为 +inf 的边,在原网络中,从S到T的流量全部流回去,流量守恒,然后转换成了无源汇的网络,然后求解无源汇上下界可行流即可。

    最终T->S 这条边的流量为原图总流量

    有源汇上下界最大流

    求出可行流之后,再求原残余网络的最大流,之前的可行流再加上残余网络最大流就是原来的最大流

    有源汇上下界最小流

    求出可行流,然后T->S的边的流量即为可行流大小,再原图残余网络中从T->S 跑最大流,用可行流减去残余网络最大流,就是最小流。

    注:原图不包括T->S 的边以及S'和T'所连接的所有边

    例题

    BZOJ-3698. XWW的难题

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    #define dbg(x...) do { cout << "33[32;1m" << #x <<" -> "; err(x); } while (0)
    void err() { cout << "33[39;0m" << endl; }
    template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
    const int N = 250 + 5;
    const int M = 1000010;
    int head[N], ver[M], edge[M], nxt[M], d[N];
    int n, m, s, t, s_, t_, tot, maxflow;
    double a[N][N];
    queue<int> q;
    void add(int x, int y, int z){
        ver[++tot] = y, edge[tot] = z, nxt[tot] = head[x], head[x] = tot;
        ver[++tot] = x, edge[tot] = 0, nxt[tot] = head[y], head[y] = tot;
    }
    bool bfs(){
        memset(d, 0, sizeof d);
        while(q.size())q.pop();
        q.push(s);d[s] = 1;
        while(q.size()){
            int x = q.front();q.pop();
            for(int i=head[x];i;i=nxt[i]){
                if(edge[i] && !d[ver[i]]){
                    q.push(ver[i]);
                    d[ver[i]] = d[x] + 1;
                    if(ver[i] == t) return 1;
                }
            }
        }
        return 0;
    }
    int dinic(int x, int flow){
        if(x == t) return flow;
        int rest = flow, k;
        for(int i=head[x];i && rest; i=nxt[i]){
           	if(edge[i] && d[ver[i]] == d[x] + 1){
                k = dinic(ver[i], min(rest, edge[i]));
                if(!k) d[ver[i]] = 0;
                edge[i] -= k;
                edge[i ^ 1] += k;
                rest -= k;
            }
        }
        return flow - rest;
    }
    void ins(int x, int y, int l, int r){
        add(x, y, r-l);
        d[x] -= l;
        d[y] += l;
    }
    int main(){
        scanf("%d", &n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%lf", &a[i][j]);
            }
        }
        tot = 1;
        s_ = 2 * n + 1, t_ = s_ + 1, s = t_ + 1, t = s + 1;
        for(int i=1;i<=n-1;i++){
            ins(s_, i,  trunc(a[i][n]), ceil(a[i][n]));
            ins(i+n, t_, trunc(a[n][i]), ceil(a[n][i]));
        }
        for(int i=1;i<n;i++){
            for(int j=1;j<n;j++){
                ins(i, j+n, trunc(a[i][j]),ceil(a[i][j]));
            }
        }
        int sum = 0;
        for(int i=1;i<=t_;i++){
            if(d[i] > 0) {
                sum += d[i];
                add(s, i, d[i]);
            } else if (d[i] < 0){
                add(i, t, -d[i]);
            }
        }
        // dbg(sum);
        add(t_, s_, inf);
        while(bfs()) maxflow += dinic(s, inf);
        // dbg(sum, maxflow);
        if(sum != maxflow) {
            puts("NO");
            return 0;
        }
        maxflow = edge[tot];
        edge[tot] = edge[tot-1] = 0;
        s = s_; t = t_;
        while(bfs()) maxflow += dinic(s, inf);
        cout << maxflow * 3 << endl;
        return 0;
    }
    

    P4843 清理雪道

    // 有源汇上下界网络流
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    #define dbg(x...) do { cout << "33[32;1m" << #x <<" -> "; err(x); } while (0)
    void err() { cout << "33[39;0m" << endl; }
    template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
    const int N = 100010 + 5;
    const int M = 100010;
    int head[N], ver[M], nxt[M], edge[M], d[N];
    int n, m, s_, t_, s, t, tot, maxflow;
    queue<int> q;
    void add(int x, int y, int z){
        ver[++tot] = y, edge[tot] = z, nxt[tot] = head[x], head[x] = tot;
        ver[++tot] = x, edge[tot] = 0, nxt[tot] = head[y], head[y] = tot;
    }
    bool bfs(){
        memset(d, 0, sizeof d);
        while(q.size())q.pop();
        q.push(s);d[s] = 1;
        while(q.size()){
            int x = q.front();q.pop();
            for(int i=head[x];i;i=nxt[i]){
                if(edge[i] && !d[ver[i]]){
                    q.push(ver[i]);
                    d[ver[i]] = d[x] + 1;
                    if(ver[i] == t) return 1;
                }
            }
        }
        return 0;
    }
    int dinic(int x, int flow){
        if(x == t) return flow;
        int rest = flow, k;
        for(int i=head[x];i && rest; i=nxt[i]){
           	if(edge[i] && d[ver[i]] == d[x] + 1){
                k = dinic(ver[i], min(rest, edge[i]));
                if(!k) d[ver[i]] = 0;
                edge[i] -= k;
                edge[i ^ 1] += k;
                rest -= k;
            }
        }
        return flow - rest;
    }
    void ins(int x, int y, int l, int r){
        add(x, y, inf);
        d[x] -= l;
        d[y] += l;
    }   
    int main(){
        scanf("%d", &n);
        tot = 1;
        s_ = 0, t_ = n + 1, s = t_ + 1, t = s + 1;
        for(int i=1;i<=n;i++){
            int k,x;scanf("%d", &k);
            while(k--){
                scanf("%d", &x);
                ins(i, x, 1, inf);
            }
            add(s_, i, inf);
            add(i, t_, inf);
        }
        for(int i=1;i<=n;i++){
            if(d[i] < 0) add(i, t, -d[i]);
            else if(d[i] > 0) add(s, i, d[i]);
        }
        add(t_, s_, inf);
        while(bfs()) maxflow += dinic(s, inf);
        int res = edge[tot]; 
        maxflow = 0;
        edge[tot] = edge[tot^1] = 0;
        s = t_, t = s_;
        while(bfs()) maxflow += dinic(s, inf);
        //dbg(res, maxflow);
        printf("%d
    ", res - maxflow);
        return 0;
    }
    

    P4553 80人环游世界

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    #define dbg(x...) do { cout << "33[32;1m" << #x <<" -> "; err(x); } while (0)
    void err() { cout << "33[39;0m" << endl; }
    template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
    const int N = 100000 + 5;
    const int M = 1000010;
    int head[N], nxt[M], ver[M], edge[M], cost[M];
    int d[N], incf[N], pre[N], v[N];
    int n, m, tot, s, t, s_, S, T, maxflow, ans;
    void add(int x, int y, int z, int c){
        ver[++tot] = y, edge[tot] = z, nxt[tot] = head[x], head[x] = tot, cost[tot] = c;
        ver[++tot] = x, edge[tot] = 0, nxt[tot] = head[y], head[y] = tot, cost[tot] = -c;
    }
    inline void ins(int x, int y, int l, int r, int c){
        add(x, y, r - l, c);
        d[x] -= l; d[y] += l;
    }
    bool spfa(){
        queue<int> q;
        memset(d, 0x3f, sizeof d);
        memset(v, 0, sizeof v);
        q.push(S);
        d[S] = 0, v[S] = 1;
        incf[S] = m;
        while(q.size()){
            int x = q.front();q.pop();
            v[x] = 0;
            for(int i=head[x];i;i=nxt[i]){
                if(!edge[i]) continue;
                int y = ver[i];
                if(d[y] > d[x] + cost[i]){
                    d[y] = d[x] + cost[i];
                    incf[y] = min(incf[x], edge[i]);
                    pre[y] = i;
                    if(!v[y]) v[y] = 1, q.push(y);
                }
            }
        }
        if(d[T] == inf) return false;
        return true;
    }
    void update(){
        int x = T;
        while(x != S){
            int i = pre[x];
            edge[i] -= incf[T];
            edge[i^1] += incf[T];
            x = ver[i^1];
        }
        maxflow += incf[T];
        ans += d[T] * incf[T];
    }
    int main(){
        tot = 1;
        scanf("%d%d", &n, &m);
        s = 2 * n + 1, t = s + 1, s_ = t + 1, S = s_ + 1, T = S + 1;
        ins(s, s_, m, m ,0);
        for(int i=1;i<=n;i++){
            ins(s_, i, 0, m, 0);
            ins(i+n, t, 0, m, 0);
            int x;scanf("%d", &x);
            ins(i, i+n, x, x, 0);
        }
        for(int i=1;i<n;i++){
            for(int j=i+1;j<=n;j++){
                int x;scanf("%d", &x);
                if(~x) ins(i+n, j, 0, m, x);
            }
        }
        ins(t, s, 0, m, 0);
        for(int i=1;i<=t;i++){
            if(d[i] > 0) add(S, i, d[i], 0);
            else if(d[i] < 0) add(i, T, -d[i], 0);
        }
        while(spfa()) update();
        cout << ans << endl;
        return 0;
    
    }
    
  • 相关阅读:
    MS SQL数据类型
    ASP中调用存储过程、语法、写法-sql server数据库
    系統存儲過程System stored procedures
    ASP调用带参数存储过程的几种方式
    解密SQLSERVER2000存储过程,函数,视图,触发器
    SQL Script 執行的時間
    各種正則表达式示例
    12款操作系统安装全程图解(菜鸟必备宝典)
    内存 : DDR2与DDR
    數據庫分頁
  • 原文地址:https://www.cnblogs.com/1625--H/p/12724977.html
Copyright © 2020-2023  润新知