Type: no source sink feasible stream
Reference self ()
Http://hi.baidu.com/evelynhe/blog/item/f1c5ba2fcbe674271e3089ad.html
The capacity of each edge satisfies certain limits, that is, there is an upper limit and a lower limit.
The upper bound is represented by ci, and the lower bound is represented by bi.
The lower bound must be full. For each edge, after the lower bound is removed, the free stream is ci-bi.
Main Idea: the stream that comes in at each point = the stream that goes out
For each vertex I
Mi = sum (lower-bound stream of all streams from point I)-sum (lower-bound stream of all streams from point I)
If Mi is greater than 0, it indicates that the point must also flow out of the free stream of Mi, then we connect a Mi edge from the source point to the point.
If Mi is smaller than 0, it indicates that the point must also flow into the free stream of Mi, then we connect a Mi edge to the sink point from the point.
If you want to find the maximum stream of S-> T, check whether the stream is full (the adjacent edge of S is full ).
If the stream is full, there is a solution; otherwise, there is no solution.
View Code
# Include <stdio. h>
# Include <string. h>
Const int MAX = 100005;
Constint INF = 1000000000;
Struct EDGE
{
Int v, c, next;
} Edge [2, 1000000];
Int E, head [MAX];
Int gap [MAX], cur [MAX];
Int pre [MAX], dis [MAX];
Int in [225], low [50000];
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: ;}
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;
}
Bool solve (int n)
{
For (int I = 1; I <= n; I ++)
{
If (in [I]> 0) add_edge (0, I, in [I], 0 );
If (in [I] <0) add_edge (I, n + 1,-in [I], 0 );
}
SAP (0, n + 1, n + 2 );
For (int I = head [0]; I! =-1; I = edge [I]. next) // The edges starting from the source point are full streams.
{
If (edge [I]. c) return false;
}
Return true;
}
Int main ()
{
Int t, n, m, a, B, c;
Scanf ("% d", & t );
While (t --)
{
E = 0;
Memset (head,-1, sizeof (head ));
Memset (in, 0, sizeof (in ));
Scanf ("% d", & n, & m );
For (int I = 0; I <m; I ++)
{
Scanf ("% d", & a, & B, & low [I], & c );
In [a]-= low [I], in [B] + = low [I];
Add_edge (a, B, c-low [I], 0 );
}
If (solve (n ))
{
Printf ("YES \ n ");
For (int I = 0; I <m; I ++)
Printf ("% d \ n", edge [(I <1) ^ 1]. c + low [I]); // The Reverse stream is the free stream, plus the lower bound stream.
}
Else printf ("NO \ n ");
Puts ("");
}
Return 0;
}