From: http://www.zlinkin.com /? P = 63

Graph theory is an important part of ACM competitions. Its models are widely used in real life. Because of its vivid expression and abstract way of thinking, It is favored by all kinds of acmers who like to work hard. This article quoted the graph theory section on the Minimum Spanning Tree of Directed Graphs, introduced the solution of zhu liu's algorithm, and combined with a series of coding techniques to implement the O (VE) algorithm of the minimum tree graph, finally, the algorithm template is provided for reference.

The concept of the Minimum Spanning Tree must be well known. Given a connected graph, a tree containing all vertices (subgraph of the source image) must be obtained to minimize the sum of edge weights. In an undirected graph, it is very easy to solve the edge due to the undirected nature. The classic Kruskal and prim algorithms are enough to solve such problems. In a directed graph, we need to add a little constraint to the definition, that is, starting from the root, and accessing all vertices along the given directed edge, and the sum of edge weights is minimized, so the problem begins to become different. We call it the least Tree Graph problem.

This problem was solved by Zhu Yongjin and Liu zhenhong in the 1960s S. It is worth mentioning that these two people are still alive and even more admired, zhu Yongjin is almost a blind man. The algorithm for solving the smallest tree chart is also well-deserved.

First, let's explain the process of the algorithm: At the beginning, the algorithm determines whether the points in all source images can be reached from the fixed root. If not, there must be no minimum tree structure. This step is a very casual search. It can be done without any nonsense. Step 2: traverse all the edges and find the smallest inbound edges of all points except the root node. The tired weighted value forms a new graph. Then, judge whether the graph has a ring. If the tree type does not exist, the tree type is the minimum tree type. The current weight is the minimum weight. Otherwise, the point is reduced, and then the second step continues to judge.

There are a series of implementation issues in detail to ensure the complexity of VE. The first step is to check the ring. For A New Graph, there are only n-1 inbound edges. For each inbound edge, the vertex pointed to is unique. Therefore, we can add from in the edge table, this indicates the starting point of the edge. Considering that if a ring exists, all the edges on the ring are reversed, and the ring is obviously homogeneous, as a result, all the rings can be found in the new graph at most for a V-time DFS, and the vertex re-labeling can be reduced during recursive return, you can use the hash array to map the duplicate labels in this step. Then it is an important edge change method. For all edges not on the ring, change the weight to w-min (V), w to the current edge, and min (V) the minimum edge weight of the currently connected V point. The mathematical significance is that when the current edge is selected, the original minimum inbound edge is abandoned. We can know that each iteration selects edge operations O (E), contraction operations O (v), and update operation O (e), at least one vertex is placed into the Spanning Tree, therefore, the computation can be completed in the V-1 step, and its complexity is O (VE ).

The above is the minimum tree graph of the fixed root. For a minimum tree graph without a fixed root, the weight of all vertices in a virtual root connection is the sum of edge weights + 1, the final result is subtracted (edge weight + 1. In addition, you only need to search for the selected virtual edge to determine the root label.

The following are some implementations of the Code:

# Include <iostream> using namespace STD; const int maxn = 1010; const int maxm = 10010; typedef struct {int V, next, RT, cost, BT, BV;} edge; int n, m, Eid; int RT, W; // uncertain root int P [maxn], in [maxn], IND [maxn], hash [maxn]; edge e [maxm]; bool vist [maxn]; int clen; inline void Init () {eid = 0; memset (p,-1, sizeof (p ));} inline void insert (int from, int to, int cost) {If (from = to) return; E [Eid]. next = P [from]; E [Eid]. V = to; E [Eid]. RT = fro M; E [Eid]. bv = to; E [Eid]. bt = from; E [Eid]. cost = cost; P [from] = Eid ++;} // fixed root // inline void DFS (int pos) // {// Int J; // For (j = P [POS]; J! =-1; j = E [J]. Next) // {// If (! Vist [E [J]. v]) // {// vist [E [J]. v] = true; // DFS (E [J]. v); //} int CNT; int st; inline bool c_dfs (int pos) {int x = ind [POS]; if (x =-1) {return false;} int v = E [X]. RT; If (! Vist [v]) {vist [v] = true; If (c_dfs (V) {hash [v] = CNT; return true;} vist [v] = false ;} else {return ST = V;} return false;} int fit; inline int rtree () {int I; // The following is an infinitus root + + W; RT = N; for (I = 0; I <n; ++ I) insert (RT, I, W); ++ N; ///////////////// specify the root type. // RT = 0 // memset (vist, 0, sizeof (vist); // vist [RT] = true; // DFS (RT); // for (I = 0; I <n; ++ I) if (! Vist [I]) {return-1;} // int res = 0; for (I = 0; I <n; ++ I) hash [I] = I; bool flag = true; int bbt = RT; int CT; Fit = int_max; while (1) {Ct = clen = CNT = 0; for (I = 0; I <n; ++ I) in [I] = int_max, IND [I] =-1; // find the smallest edge for (I = 0; I <Eid; ++ I) {int FF = E [I]. RT; int TT = E [I]. v; If (FF = TT) {continue;} If (E [I]. cost <in [TT]) {in [TT] = E [I]. cost; ind [TT] = I ;}} in [RT] = 0; ind [RT] =-1; for (I = 0; I <n; ++ I) {int x = ind [I]; If (x =-1) continue; If (E [x ]. Bt = bbt) {++ CT; If (E [X]. BV <fit) fit = E [X]. BV ;}} memset (vist, 0, sizeof (vist); // find the ring for (I = 0; I <n; ++ I) {If (! Vist [I]) {vist [I] = true; hash [I] = CNT; ST = I; If (c_dfs (I) {++ clen; ++ CNT; continue;} vist [I] = false; ++ CNT ;}}for (I = 0; I <n; ++ I) {res ++ = in [I];} if (clen = 0) {break;} // scale down and change the edge for (I = 0; I <Eid; ++ I) {int ff, TT; FF = E [I]. RT; TT = E [I]. v; E [I]. RT = hash [E [I]. RT]; E [I]. V = hash [E [I]. v]; If (E [I]. rt! = E [I]. v) {e [I]. Cost-= in [TT] ;}} n = CNT; RT = hash [RT] ;}if (CT! = 1) Return-1; return res-W ;}