[Summary] magical online and offline network streams -- (Summary by: becauseofyou)

Source: Internet
Author: User

I still remember that I did the online and offline network stream question in the last year, but at that time I only set up the online graph creation method to understand the internal principles, therefore, when I encountered this question a few days ago, it was a little messy. So I learned it again and understood it deeply. It is estimated that I will not forget it again.

Now, let's get down to the truth.

This blog is well written for upstream and downstream network streams. It introduces how to create a graph and how to solve it. Then this article is more mathematical and theoretical, but it is easy to understand.

Well, then I will stand on the shoulders of giants and sum up.

There are four types of network flow problems.

1: No source sink Feasible Flow sgu 194

2
Poj 2396 is a good question. I have created nearly 200 rows of images.

3: the question of zoj 3496, the largest stream with a source sink, is fierce and requires two points.

4: minimum stream with a source sink
HDU 3157 sgu176

The following three methods are first converted into a non-source sink, so we will focus on how to do a network stream with no source sink. I will not repeat the above two links.

Assume that the upper bound stream of an edge is r lower bound stream is l, then the R-L is free flow, that is, as long as the flow of the L, the next to the stream How casual.

A feasible upstream/downstream stream without a source sink is a solution. The stream is circulating in the stream, and each point is equal to the inflow. Let's further subdivided into sigma (lower-bound stream in) + sigma (free stream in) = sigma (lower-bound stream out) + sigma (free stream out)

Assume that we want to convert this network flow problem to a normal maximum flow problem. First, we need to remove the lower bound, that is, the lower bound is 0. After removal, We need to overlay the lower bound factors in the source image. How can we overlay them? Assume that the sum of lower-bound streams in a vertex minus the sum of lower-bound flows out is M. If M is positive, the incoming free streams are less m than the outgoing free streams, so we manually add m to this point (think about why ). If M is negative, it is similar. It streams out M from the current point. A source point and a sink point need to be built for adding traffic and streaming out.

Why is there a solution if the edge of the source point is full after the graph is created to find the maximum stream?

Think about it. What does it mean if the outbound edge of the source point is full of streams ?? We can regard the network in the middle as a black box. The source point is the entrance, and the sink point is the exit, whether it is a circulating stream or directly passing through a chain to the sink point, we don't care, we only care about whether the inbound stream can flow out, that is, whether the network in the black box can support the stream. If yes, it indicates that the original network can support free streams that must be streamed. That means there is a solution for the original network!


The maximum flow of the upper and lower bounds of the source sink is: edge is built from the sink point T to the source point S (the upper bound is INF, and the lower bound is 0). (This step is very sharp, wait a moment to explain why it is sharp), convert it to a network stream problem with no source sink, use the above method to determine whether there is a solution, if there is a solution, then run the largest stream from the source node s to the sink node T again, now the biggest stream is the answer...

The previous step was sharp and sharp. After only one side was built, the source image was converted into another problem that can be solved (maybe you don't feel sharp, however, it seems sharp to come up with this method from scratch)

When we run the largest stream for the first time, we can actually solve the traffic of a feasible stream in the network. This traffic is actually the reverse stream of the last added edge. Because the lower bound is 0 when it is added, it is obviously correct.


Why can I find the answer when I run the largest stream again?

Because the first operation is a feasible stream, there may be some other sides that can be first-class, so you can run it again, the original feasible stream's traffic was recorded in the T-> S reverse stream. Because this stream is streamed back once again, it is the answer again!


Well, since there is a lower bound, you can certainly find the smallest stream.

First, run the maximum stream in the source image, connect the T-> S (0, INF) side, and then run it again.

Why is the traffic at the first time not the smallest flow? The first blog has already explained why)

Example: poj 2396.

There is a matrix that tells you the sum of each row and the sum of each column, and there are some limitations. In combination, it actually tells you the range of a number [I] [J, however, you have to find it by yourself. Finally, you can check whether such a matrix exists.

If you want to take a closer look, we can see that this is a very bare upstream and downstream stream, but you need to split it first, 1 ~ N * m indicates the point in the matrix, N * m + 1 ~ To 2 * n * m indicates the split point, 2 * n * m + 1 ~ 2 * n * m + M indicates each row, 2 * n * m + 1 ~ 2 * n * m + n indicates each column. The sum of the rows and columns can be limited by the creation of source points and sink points, the upper and lower bounds of these edges are a fixed value, and the rest are relatively simple. It is OK to set a feasible upstream and downstream stream with a source sink.

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int MAX=10100;const int INF=1000000000;struct EDGE{int v,c,next;}edge[101000];int E,head[MAX];int gap[MAX],cur[MAX];int pre[MAX],dis[MAX];void add_edge(int s,int t,int c,int cc){edge[E].v=t; edge[E].c=c;edge[E].next=head[s];head[s]=E++;edge[E].v=s; edge[E].c=cc;edge[E].next=head[t];head[t]=E++;}int min(int a,int b){return (a==-1||b<a)?b:a;}int SAP(int s,int t,int n){memset(gap,0,sizeof(gap));memset(dis,0,sizeof(dis));int i;for(i=0;i<n;i++)cur[i]=head[i];int u=pre[s]=s,maxflow=0,aug=-1,v;gap[0]=n;    while(dis[s]<n){loop:    for(i=cur[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(edge[i].c>0&&dis[u]==dis[v]+1) { aug=min(aug,edge[i].c); pre[v]=u; cur[u]=i; u=v; if(u==t) { for(u=pre[u];v!=s;v=u,u=pre[u]) { edge[cur[u]].c-=aug; edge[cur[u]^1].c+=aug; } maxflow+=aug; aug=-1; } goto loop; } } int mindis=n; for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(edge[i].c>0&&dis[v]<mindis) { cur[u]=i; mindis=dis[v]; } } if((--gap[dis[u]])==0)break; gap[dis[u]=mindis+1]++; u=pre[u];}return maxflow;}int m , n , S, T;int sum_row[210] , sum_col[210];int low[210][210] , up[210][210] ,in[10010];bool judge(int i,int j,char op,int c){if(op=='='){if(c >= low[i][j] && c <= up[i][j]){low[i][j] = c;up[i][j]  = c;}else return false;}else if(op=='>'){low[i][j] = max(low[i][j],c+1);if(low[i][j] > up[i][j]) return false;}else {up[i][j] = min(up[i][j],c-1);if(low[i][j] > up[i][j]) return false;}return true;}bool init(){E=0;memset(head,-1,sizeof(head));memset(in,0,sizeof(in));int i , j , k , a, b , c;scanf("%d%d",&m,&n);int tot = 2 * n * m; S = 0; T = tot + n + m + 1;for(i = 1; i <= m; i++){scanf("%d",&sum_row[i]);in[i+tot] = sum_row[i];in[S] -= sum_row[i];//add_edge(S,i+tot,sum_row[i],0);}for(i = 1; i <= n; i++){scanf("%d",&sum_col[i]);in[T] += sum_col[i];in[m+tot+i] = - sum_col[i];//add_edge(m+tot+i,T,sum_col[i],0);}add_edge(T,S,INF,0);scanf("%d",&k); char op[5];for(i = 1; i <= m; i++) for(j = 1; j <= n; j++) low[i][j] = 0, up[i][j] = 200000;bool flag = true;for(int x = 0; x < k; x++){scanf("%d%d%s%d",&a,&b,op,&c);if(!a){if(!b){for(i = 1; i <= m; i++){for(j = 1; j <= n; j++){if(!judge(i,j,op[0],c)) flag = false;}}}else {for(i = 1; i <= m; i++){if(!judge(i,b,op[0],c)) flag = false;}}}else {if(!b){for(i = 1; i <= n; i++){if(!judge(a,i,op[0],c)) flag = false;}}else {if(!judge(a,b,op[0],c)) flag = false;}}}/*for(i = 1; i <= m; i++){for(j = 1; j <= n; j++){printf("i = %d j = %d  %d %d \n",i , j , low[i][j],up[i][j] );}}*/return flag;}int ID(int i,int j){return (i-1)*n+j;}int ans[250][250];bool check(){for(int i = 1; i <= m; i++){int s = 0;for(int  j =1; j <=n;j ++){s += ans[i][j];}if(s!=sum_row[i]) return false;}for(int i = 1; i <= n; i++){int s =  0;for(int j = 1; j <= m; j++){s += ans[j][i];}if(s!=sum_col[i]) return false;}return true;}bool solve(){int i , j , k;for(i = 1; i <= m; i++){for(j = 1; j <= n; j++){int c = up[i][j] - low[i][j];int id = ID(i,j);//printf("i=%d j=%d  id = %d %d c = %d\n",i,j,id,id+n*m,c);add_edge(id,id+n*m,c,0);in[id] -= low[i][j];in[id+n*m] += low[i][j];}}int ss = T + 1, tt = ss + 1;for(i = 1; i <= m; i++){for(j = 1; j <= n; j++){add_edge(2*n*m+i,ID(i,j),200000,0);}}for(i = 1; i <= n; i++){for(j = 1; j <= m; j++){//printf("%d %d\n",2*n*m+m+i,ID(j,i)+n*m);add_edge(ID(j,i)+m*n,2*m*n+m+i,200000,0);}}for(i = 0; i <= 2*m*n+m+n+1 ; i++){//printf("in[%d]=%d\n",i,in[i]);if(in[i] > 0) add_edge(ss,i,in[i],0);if(in[i] < 0) add_edge(i,tt,-in[i],0);}SAP(ss,tt,tt+1);for(i=head[ss];i!=-1;i=edge[i].next){if(edge[i].c) return false;}for(i = 1; i <= m; i++){for(j = 1; j <= n; j++){int id = ID(i,j);for(k = head[id]; k!=-1; k=edge[k].next){if(edge[k].v <= 2*n*m){ans[i][j] = low[i][j] + edge[k^1].c;}}}}for(i = 1; i <= m; i++){printf("%d",ans[i][1]);for(j = 2; j <= n; j++){printf(" %d",ans[i][j]);}puts("");}/*if(check()) {puts("YES");} else puts("NO");*/return true;}int main(){int t;//freopen("budget.in","r",stdin);//freopen("budget.out","w",stdout);scanf("%d",&t);for(int i = 0; i < t; i++){if(i) puts("");if(!init()){puts("IMPOSSIBLE");}else {if(!solve()) puts("IMPOSSIBLE");}}return 0;}

Zoj is a very good question. It requires two points, but it is not very easy to write. Attach the code.

Http://acm.zju.edu.cn/onlinejudge/showProblem.do? Problemcode = 3496 # include <stdio. h> # include <string. h> typedef long LLD; const int max = 510; const int INF = 100000000; struct edge {int V, C, next;} edge [1000000]; int e, head [Max]; int gap [Max], cur [Max]; int pre [Max], DIS [Max]; void add_edge (int s, int T, int C, int CC) {edge [e]. V = T; edge [e]. C = C; edge [e]. next = head [s]; head [s] = e ++; edge [e]. V = s; edge [e]. C = cc; edge [e]. next = head [T]; head [T] = e ++;} int min (int A, int B) {return (A =-1 | B <)? B: A;} int SAP (INT S, int T, int N) {memset (GAP, 0, sizeof (GAP); memset (DIS, 0, sizeof (DIS); int I; for (I = 0; I <n; I ++) cur [I] = head [I]; int u = pre [s] = s, Aug =-1, V; int maxflow = 0; Gap [0] = N; while (DIS [s] <n) {loop: for (I = cur [u]; I! =-1; I = edge [I]. next) {v = edge [I]. v; If (edge [I]. c> 0 & dis [u] = dis [v] + 1) {Aug = min (Aug, edge [I]. c); Pre [v] = u; cur [u] = I; u = V; If (u = T) {for (u = pre [u]; V! = S; V = u, u = pre [u]) {edge [cur [u]. c-= Aug; edge [cur [u] ^ 1]. c + = Aug;} maxflow + = Aug; Aug =-1;} goto loop;} int mindis = N; for (I = head [u]; I! =-1; I = edge [I]. next) {v = edge [I]. v; If (edge [I]. c> 0 & dis [v] <mindis) {cur [u] = I; mindis = dis [v] ;}} if (-- gap [dis [u]) = 0) break; Gap [dis [u] = mindis + 1] ++; u = pre [u];} return maxflow;} int n, m, S, T, P, ans1, ans2, maxc, minc; int max_flow; int U [10010], V [10010], c [10010]; int in [510]; void Init () {e = 0; memset (Head,-1, sizeof (head [0]) * 600 );} void map_init (INT mid) // The traffic upper bound is mid, and the upper bound of each edge is the minimum value of mid and c {Init (); For (INT I = 0; I <m; I ++) {add_edge (U [I], V [I], min (MID, C [I]), 0) ;}} void question1 () // binary upper limit {int L = 0, r = maxc; while (L <= r) {int mid = L + r> 1; map_init (MID); int TMP = SAP (s, t, n); If (TMP = max_flow) {ans1 = mid; R = mid-1 ;}else {L = Mid + 1 ;}} bool map_init (INT mid) // mid is the lower bound {Init (); memset (in, 0, sizeof (in); For (INT I = 0; I <m; I ++) {If (C [I] <mid) return false; add_edge (U [I], V [I], C [I]-mid, 0); in [V [I] + = mid; in [U [I]-= mid;} return true;} bool OK (INT mid) {int I, j; If (! Map_init (MID) return false; int Ss = N, TT = n + 1; for (I = 0; I <n; I ++) {If (in [I]> 0) add_edge (SS, I, in [I], 0); If (in [I] <0) add_edge (I, TT, -In [I], 0);} add_edge (t, s, INF, 0); SAP (SS, TT, tt + 1 ); for (I = head [ss]; I! =-1; I = edge [I]. next) {If (edge [I]. c) Return false;} return SAP (S, T, tt + 1) = max_flow;} void question2 () // lower limit of binary {int L = 0, r = maxc; // theoretically, this R can be assigned to minc, But wa (because if it is greater than minc, the upper bound of the edge must be smaller than the lower bound) while (L <= r) {int mid = L + r> 1; if (OK (MID) {ans2 = mid; L = Mid + 1 ;} else {r = mid-1 ;}} int main () {int T, I, J, K; scanf ("% d", & T ); while (t --) {scanf ("% d", & N, & M, & S, & T, & P ); init (); maxc = 0; minc = inf; for (I = 0; I <m; I ++) {scanf ("% d ", & U [I], & V [I], & C [I]); add_edge (U [I], V [I], C [I], 0 ); if (C [I]> maxc) maxc = C [I]; If (C [I] <minc) minc = C [I];} max_flow = SAP (S, t, n); question1 (); question2 (); printf ("% LLD \ n", (LLD) ans1 * P, (LLD) ans2 * P );} return 0 ;} /* 1004 3 0 3 30 1 21 2 32 3 44 5 0 3 20 1 20 2 11 2 11 3 12 3 24 5 0 3 20 1 10 2 11 2 21 3 22 3 15 5 0 4 10 3 10 2 13 1 12 1 11 4 16 64 22 01 0 */

Finally, I will summarize the graph creation method to help you quickly recall the event.

1: a feasible stream without a source sink: New Source Vertex, sink vertex, and m [I] are the lower bound streams of each vertex. If M [I] is positive, the edge of M [I] is built from the Source Vertex to the transformed vertex. On the contrary, the edge of M [I] is built from the vertex to the sink vertex. the edge in the source image is the upper bound of each edge and the lower bound is created. When you run the maximum stream once, the traffic on each edge plus the lower bound stream is the answer.

2: The largest stream with a source sink: Build an INF edge from the sink to the Source Vertex, use the above method to determine whether there is a solution, and then run the largest stream from the Source Vertex to the sink vertex again

3: The smallest stream with a source sink: first run the largest stream, then connect the edge from the sink to the source, and then follow the 1 method.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.