上下界网络流

 

 

上下界网络流  链接

转自: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\n", res);
            for(int i = 0; i < m; i++){
                printf("%d%c", e[id[i]].flow + ans[i], (i == m-1 ? '\n' : ' '));
            }
        }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\n", e[id[i]].flow + ans[i]);
133             }
134         }else{
135             puts("NO");
136         }
137     }
138 
139 }
View Code

 

posted @ 2017-11-22 19:48  yijiull  阅读(125)  评论(0编辑  收藏  举报