• 上下界网络流


    上下界网络流  链接

    转自:http://blog.csdn.net/leolin_/article/details/7208246

     一、有源汇、无源汇的可行流。
      求可行流,其实就是问是否存在一个方案可以使所有必须边都满流。对于有源汇的网络,我们可以添加一条边t->s,流量上限为INF,这样就变成了无源汇的网络。对于无源汇的网络,只要对ss到tt求一次最大流,若所有必须边都满流,则有可行解,若要求打印方案,只需将非必须边中流过的流量加上流量下界(必须边已满流)。
     
    二、有源汇的最大流
      这里的最大流,前提是使所有必须边满流,再要求从s到t的流量最大(注意,这里所求的最大流是原网络的最大流,而我们求ss到tt的最大流只是用于判断是否能使所有必须边满流)。首先判断所有必须边是否满流,这里和问题一中提到的方法一样,注意这里是有源汇的网络。然后直接对残留网络求一次从s到t的最大流,这个最大流再加上流量下界就是最终答案。
     
    三、有源汇的最小流
      和问题二相反,我们要使所有必须边满流的情况下,要求从s到t的流量最小。这个问题比上面的问题都要复杂,分三个步骤。
    1、对ss到tt求一次最大流,记为f1。(在有源汇的情况下,先使整个网络趋向必须边尽量满足的情况)
    2、添加一条边t->s,流量上限为INF,这条边记为p。(构造无源汇网络)
    3、对ss到tt再次求最大流,记为f2。(要判断可行,必须先构造无源汇网络流,因此要再次求最大流)
     
    如果所有必须边都满流,证明存在可行解,原图的最小流为“流经边p的流量”(原图已构造成无源汇网络,对于s同样满足入流 == 出流,只有新添加的边流向s,而s的出流就是原图的最小流)。

    Flow construction

     SGU - 176 

     8PE!!!!!!!!!!

    #include <bits/stdc++.h>
    using namespace std;
    const int maxv = 20005;
    const int maxe = 20005;
    const int inf = 0x3f3f3f3f;
    struct Edge{
        int u, v, cap, flow, nxt;
        Edge(int u = 0, int v = 0, int cap = 0, int flow = 0, int nxt = 0) : 
            u(u), v(v), cap(cap), flow(flow), nxt(nxt) {}
    }e[maxe<<1];
    int head[maxv];
    int cnt;
    void init(){
        cnt = 0;
        memset(head, -1, sizeof(head));
    }
    void add(int u, int v, int cap){
        e[cnt] = Edge(u, v, cap, 0, head[u]);
           head[u] = cnt++;
        e[cnt] = Edge(v, u, 0, 0, head[v]);
        head[v] = cnt++;
    }
    
    int d[maxv], num[maxv], p[maxv], cur[maxv];
    int vis[maxv];
    int s, t;
    int N;
    
    void bfs(){
        memset(vis, 0, sizeof(vis));
        memset(d, -1, sizeof(d));
        queue<int> q;
        q.push(t);
        d[t] = 0;
        vis[t] = 1;
        while(!q.empty()){
            int u = q.front();
            q.pop();
            for(int i = head[u]; ~i; i = e[i].nxt){
                int id = i & (-2);
                int v = e[id].u;
                if(!vis[v] && e[id].cap > e[id].flow){
                    vis[v] = 1;
                    d[v] = d[u] + 1;
                    q.push(v);
                }
            }
        }
    }
    
    int augment(){
        int u = t, a = inf;
        while(u != s){
            int id = p[u];
            a = min(a, e[id].cap - e[id].flow);
            u = e[id].u;
        }
        u = t;
        while(u != s){
            int id = p[u];
            e[id].flow += a;
            e[id ^ 1].flow -= a;
            u = e[id].u;
        }
        return a;
    }
    
    int ISAP(){
        bfs();
        int flow = 0;
        memset(num, 0, sizeof(num));
        for(int i = 0; i < N; i++){
            cur[i] = head[i];
            if(~d[i]) num[d[i]]++;
        }
        int u = s;
        while(d[s] < N){
            if(u == t){
                flow += augment();
                u = s;
            }
            int ok = 0;
            for(int i = cur[u]; ~i; i = e[i].nxt){
                int v = e[i].v;
                if(d[u] == d[v] + 1 && e[i].cap > e[i].flow){
                    ok = 1;
                    p[v] = i;
                    cur[u] = i;
                    u = v;
                    break;
                }
            }
            if(!ok){
                int m = N - 1;
                for(int i = head[u]; ~i; i = e[i].nxt){
                    if(e[i].cap > e[i].flow && ~d[e[i].v]) m = min(m, d[e[i].v]);
                }
                if(--num[d[u]] == 0) break;
                num[d[u] = m + 1]++;
                cur[u] = head[u];
                if(u != s) u = e[p[u]].u;
            }
        }
        return flow;
    }
    
    int ans[maxe], id[maxe];
    
    int main(){
        int n, m;
    
        freopen("in.txt", "r", stdin);
        freopen("out2.txt", "w", stdout);
        while(scanf("%d %d" , &n, &m) != EOF){
            int u, v, cap, d;
            init();
            int S = 0, T = n + 1;
            int sum = 0;
            for(int i = 0; i < m; i++){
                scanf("%d %d %d %d", &u, &v, &cap, &d);
                id[i] = maxe - 1;
                if(d){
                    sum += cap;
                    add(u, T, cap);
                    add(S, v, cap);
                    ans[i] = cap;
                }else{
                    ans[i] = 0;
                    add(u, v, cap);
                    id[i] = cnt - 2;
                }
            }
            s = S;
            t = T;
            N = n + 2;
            int pre = ISAP();
            add(n, 1, inf);
            int res = ISAP();
            int flow = res + pre;
            //cout<<pre<<"  "<<res<<" "<<flow<<endl;
            if(sum == flow){
                printf("%d
    ", res);
                for(int i = 0; i < m; i++){
                    printf("%d%c", e[id[i]].flow + ans[i], (i == m-1 ? '
    ' : ' '));
                }
            }else{
                puts("Impossible");
            }
        }
    
    }

    Reactor Cooling

     SGU - 194 

    求有上下界的无源无汇的最小可行流。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int maxv = 210;
      4 const int maxe = 210 * 210 * 6;
      5 const int inf = 0x3f3f3f3f;
      6 struct Edge{
      7     int u, v, cap, flow, nxt;
      8     Edge(int u = 0, int v = 0, int cap = 0, int flow = 0, int nxt = 0) : 
      9         u(u), v(v), cap(cap), flow(flow), nxt(nxt) {}
     10 }e[maxe];
     11 int head[maxv];
     12 int cnt;
     13 void init(){
     14     cnt = 0;
     15     memset(head, -1, sizeof(head));
     16 }
     17 void add(int u, int v, int cap){
     18     e[cnt] = Edge(u, v, cap, 0, head[u]);
     19        head[u] = cnt++;
     20     e[cnt] = Edge(v, u, 0, 0, head[v]);
     21     head[v] = cnt++;
     22 }
     23 
     24 int d[maxv], num[maxv], p[maxv], cur[maxv];
     25 int vis[maxv];
     26 int s, t;
     27 int N;
     28 
     29 void bfs(){
     30     memset(vis, 0, sizeof(vis));
     31     memset(d, -1, sizeof(d));
     32     queue<int> q;
     33     q.push(t);
     34     d[t] = 0;
     35     vis[t] = 1;
     36     while(!q.empty()){
     37         int u = q.front();
     38         q.pop();
     39         for(int i = head[u]; ~i; i = e[i].nxt){
     40             int id = i & (-2);
     41             int v = e[id].u;
     42             if(!vis[v] && e[id].cap > e[id].flow){
     43                 vis[v] = 1;
     44                 d[v] = d[u] + 1;
     45                 q.push(v);
     46             }
     47         }
     48     }
     49 }
     50 
     51 int augment(){
     52     int u = t, a = inf;
     53     while(u != s){
     54         int id = p[u];
     55         a = min(a, e[id].cap - e[id].flow);
     56         u = e[id].u;
     57     }
     58     u = t;
     59     while(u != s){
     60         int id = p[u];
     61         e[id].flow += a;
     62         e[id ^ 1].flow -= a;
     63         u = e[id].u;
     64     }
     65     return a;
     66 }
     67 
     68 int ISAP(){
     69     bfs();
     70     int flow = 0;
     71     memset(num, 0, sizeof(num));
     72     for(int i = 0; i < N; i++){
     73         cur[i] = head[i];
     74         if(~d[i]) num[d[i]]++;
     75     }
     76     int u = s;
     77     while(d[s] < N){
     78         if(u == t){
     79             flow += augment();
     80             u = s;
     81         }
     82         int ok = 0;
     83         for(int i = cur[u]; ~i; i = e[i].nxt){
     84             int v = e[i].v;
     85             if(d[u] == d[v] + 1 && e[i].cap > e[i].flow){
     86                 ok = 1;
     87                 p[v] = i;
     88                 cur[u] = i;
     89                 u = v;
     90                 break;
     91             }
     92         }
     93         if(!ok){
     94             int m = N - 1;
     95             for(int i = head[u]; ~i; i = e[i].nxt){
     96                 if(e[i].cap > e[i].flow && ~d[e[i].v]) m = min(m, d[e[i].v]);
     97             }
     98             if(num[--d[u]] == 0) break;
     99             num[d[u] = m + 1]++;
    100             cur[u] = head[u];
    101             if(u != s) u = e[p[u]].u;
    102         }
    103     }
    104     return flow;
    105 }
    106 
    107 int ans[maxe], id[maxe];
    108 
    109 int main(){
    110     int n, m;
    111     while(scanf("%d %d" , &n, &m) != EOF){
    112         int u, v, cap, d;
    113         init();
    114         int S = 0, T = n + 1;
    115         int sum = 0;
    116         for(int i = 0; i < m; i++){
    117             scanf("%d %d %d %d", &u, &v, &d, &cap);
    118             add(u, v, cap - d);
    119             id[i] = cnt - 2;
    120             add(u, T, d);
    121             add(S, v, d);
    122             sum += d;
    123             ans[i] = d;
    124         }
    125         s = S;
    126         t = T;
    127         N = n + 2;
    128         int flow = ISAP();
    129         if(sum == flow){
    130             puts("YES");
    131             for(int i = 0; i < m; i++){
    132                 printf("%d
    ", e[id[i]].flow + ans[i]);
    133             }
    134         }else{
    135             puts("NO");
    136         }
    137     }
    138 
    139 }
    View Code
  • 相关阅读:
    支付包接口支付缓存问题
    vue多层弹框时存在遮挡应如何解决
    P1520 因式分解 题解
    观测概率为多维高斯分布时对两(多)类MAP决策边界的分析
    关于因数个数的估计
    使用ITTP_Stream显示图像
    linux某个目录没有可执行权限
    linux ldd命令
    注意力机制
    transformer
  • 原文地址:https://www.cnblogs.com/yijiull/p/7880956.html
Copyright © 2020-2023  润新知