Question link http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4700
Gomory-hutree http://en.wikipedia.org/wiki/Gomory%E2%80%93Hu_tree
Definition of gomory-hu tree
LetG= ((VG,EG ),C) Be an undirected graphC(U,V) Being the capacity of the edge (U,V) Respectively.
-
Denote the minimum capacity of
S-
TCut by λ st for each
S,
Tε
VG.
-
Let
T= (
VT,
ET) be a tree
VT =
VG, denote the set of edges in
S-
TPath
PSt for each
S,
Tε
VT.
ThenTIs said to beGomory-hu treeOfGIf
-
λ ST = mine ε PST
C(
SE,
TE) for all
S,
Tε
VG,
Where
- SE andTE are the two connected componentsTElse {E} In the sense that (SE,
TE) FormS-TCut inG, And
- C(SE,TE) is the capacity of the cut inG.
In general, the S, T, and gomory-hu trees of any two nodes store the largest stream of their adjacent nodes.
If the maximum stream of two vertices is required, the weight of the smallest edge of the vertex S is obtained from the edge of the tree to T.
In this case, the explanation in the standard question is: if there is a picture of such a requirement, the corresponding gomory-hu tree will inevitably exist,
Set the non-adjacent edge of the gomory-hu tree to 0, which is an answer that can be established.
Standard question:
Recursive Construction
Make F branch = Mina branch = B FA, B
Make a = {v0} into {v: FV, V0> F }}, B = {v: FV, V0 = f }.
If B = fail
If Merge (a, a, B, B) FA, B> F then, it fails
Recursively Construct A and B
Take a branch a, B branch B, and edge (a branch, B Branch). The capacity is f branch.
Code:
# Include <cassert> # include <cstdio> # include <cstring> # include <climits> # include <vector> # include <algorithm> # define size (V) (INT) (V ). size () # define foreach (I, V) for (_ typeof (V ). begin () I = (V ). begin (); I! = (V ). end (); ++ I) const int n = 100; int N, cut [N] [N], graph [N] [N]; bool check (STD :: vector <int> vs) {If (SIZE (VS) <= 1) {return true;} int bridge = int_max; foreach (u, VS) {foreach (v,) {bridge = STD: min (BRIDGE, cut [* u] [* V]) ;}} int U0 =. front (); STD: vector <int> v0, V1; foreach (ITER, VS) {int v = * ITER; If (cut [U0] [v]> Bridge) {v0.push _ back (v) ;}else {v1.push _ back (v) ;}} if (V 0. empty () | v1.empty () {return false;} graph [v0.front ()] [v1.front ()] = graph [v1.front ()] [v0.front ()] = bridge; foreach (u, V0) {// The maximum stream between V0 and V1 is bridge. If the flow (a, B)> Bridge in the given condition is in conflict with the condition, the image foreach (v, V1) {If (cut [* u] [* V]! = Bridge) {return false ;}}return check (v0) & check (V1) ;}int main () {// freopen ("1005.in"," r ", stdin); // freopen ("10050.out"," W ", stdout); freopen (" temp. in "," r ", stdin); While (scanf (" % d ", & n) = 1) {// printf (" % d \ n ", n); Assert (1 <= N & n <= N); For (INT I = 0; I <n; ++ I) {for (Int J = 0; j <n; ++ J) {assert (scanf ("% d", & cut [I] [J]) = 1); // If (J! = N-1) printf ("% d", cut [I] [J]); // else printf ("% d", cut [I] [J]); if (I = J) {assert (cut [I] [J] =-1); cut [I] [J] = int_max ;} else {assert (0 <= cut [I] [J] & cut [I] [J] <= 1000000000) ;}// puts ("");} for (INT I = 0; I <n; ++ I) {for (Int J = 0; j <n; ++ J) {assert (cut [I] [J] = cut [J] [I]) ;}} STD: vector <int> vertices; For (INT I = 0; I <n; ++ I) {vertices. push_back (I);} memset (graph, 0, S Izeof (graph); For (INT I = 0; I <n; ++ I) {graph [I] [I] =-1 ;} if (check (vertices) {puts ("yes"); For (INT I = 0; I <n; ++ I) {for (Int J = 0; j <n; ++ J) {// printf ("% d % C", I = J? -1: 0, j = n-1? '\ N': ''); printf (" % d % C ", graph [I] [J], j = n-1? '\ N': '') ;}} else {puts (" no ") ;}}// puts (check (vertices )? "Yes": "no"); Return 0 ;}