朱 - 刘算法
· 定義
對于有向無環圖$G (V, E)$,類似最小生成樹的定義,有向圖最小樹形圖即在有向圖上查找總權值和最小的樹形圖(即有向邊的樹)。
· 朱 - 劉算法
對于每個點先選取到達它的最小的邊,這樣可組成一個邊集E1,顯然,該邊集權值和最小,但不一定是樹。
在該邊集上進行縮點,并判斷是否有解(是否有點無入度,或若有根無出度),在融會$G$中,記為G1。
當然,若此時沒有找到有向環且有解,說明在當前圖上已找到最小樹形圖,那么將原來的縮點解開,即除了當前樹形圖上的弧之外,將縮點內沒有與已知弧有相同終點的邊選出,如此構成了G的最小樹形圖。
反之,則進行改邊:先省去縮點內邊;對于由縮點內出去的邊,保持原權值即可;對于進入縮點的邊,令Vs表示縮點點集,對于?v ∈ Vs,?u ? Vs,有<u, V> = <u, v> - v的最小入權邊,是因為這樣將權值相加的話,就相當于刪去了縮點中擁有相同終點的邊。
這樣更改完點集與邊集,進行重復運算即可。
對于無根樹,建立超級根節點即可。
其中,復雜度$O (nm)$。
· 代碼
(該代碼僅求最小權值總和,這樣是不需解開縮點的)
?
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 typedef long long LL; 8 9 const int MAXN = 100 + 10; 10 const int MAXM = 1e04 + 10; 11 12 const int INF = 0x7fffffff; 13 14 struct Edge { 15 int u, v; 16 int w; 17 18 Edge () {} 19 20 Edge (int fu, int fv, int fw) : 21 u (fu), v (fv), w (fw) {} 22 } ; 23 24 Edge Edges[MAXM]; 25 26 LL ans = 0; 27 28 int Inw[MAXN]; 29 int pre[MAXN]; 30 31 int Belong[MAXN]; 32 int Vis[MAXN]; 33 34 void Zhu_Liu (int root, int V, int E) { 35 while (true) { 36 for (int i = 1; i <= V; i ++) 37 Inw[i] = INF; 38 39 for (int i = 1; i <= E; i ++) { 40 int u = Edges[i].u; 41 int v = Edges[i].v; 42 int w = Edges[i].w; 43 44 if (u == v) 45 continue; 46 47 if (w < Inw[v]) { 48 Inw[v] = w; 49 pre[v] = u; 50 } 51 } 52 53 for (int i = 1; i <= V; i ++) 54 if (Inw[i] == INF && i != root) { 55 ans = - 1; 56 57 return ; 58 } 59 60 memset (Belong, - 1, sizeof (Belong)); 61 memset (Vis, - 1, sizeof (Vis)); 62 Inw[root] = 0; 63 64 int cnt = 0; 65 for (int i = 1; i <= V; i ++) { 66 ans += Inw[i]; 67 68 int pres = i; 69 while (Vis[pres] != i && Belong[pres] == - 1 && pres != root) { 70 Vis[pres] = i; 71 pres = pre[pres]; 72 } 73 74 if (Belong[pres] == - 1 && pres != root) { 75 cnt ++; 76 for (int p = pre[pres]; p != pres; p = pre[p]) 77 Belong[p] = cnt; 78 Belong[pres] = cnt; 79 } 80 } 81 82 if (! cnt) 83 break; 84 85 for (int i = 1; i <= V; i ++) 86 if (Belong[i] == - 1) 87 Belong[i] = ++ cnt; 88 89 for (int i = 1; i <= E; i ++) { 90 int u = Edges[i].u; 91 int v = Edges[i].v; 92 93 Edges[i].u = Belong[u]; 94 Edges[i].v = Belong[v]; 95 96 if (Belong[u] != Belong[v]) 97 Edges[i].w -= Inw[v]; 98 } 99 100 V = cnt; 101 root = Belong[root]; 102 } 103 } 104 105 int N, M, Root; 106 107 int Outdeg[MAXN]= {0}; 108 109 int main () { 110 scanf ("%d%d%d", & N, & M, & Root); 111 112 for (int i = 1; i <= M; i ++) { 113 int u, v, w; 114 scanf ("%d%d%d", & u, & v, & w); 115 116 Edges[i] = Edge (u, v, w); 117 Outdeg[u] ++; 118 } 119 120 if (! Outdeg[Root]) 121 ans = - 1; 122 else 123 Zhu_Liu (Root, N, M); 124 125 printf ("%lld\n", ans); 126 127 return 0; 128 } 129 130 /* 131 4 6 1 132 1 2 3 133 1 3 1 134 4 1 2 135 4 2 2 136 3 2 1 137 3 4 1 138 */ 139 140 /* 141 4 6 3 142 1 2 3 143 1 3 1 144 4 1 2 145 4 2 2 146 3 2 1 147 3 4 1 148 */ 149 150 /* 151 4 6 2 152 1 2 3 153 1 3 1 154 4 1 2 155 4 2 2 156 3 2 1 157 3 4 1 158 */ View Code?
轉載于:https://www.cnblogs.com/Colythme/p/9710789.html
總結
- 上一篇: [LeetCode] 142. Link
- 下一篇: 用QPCR检测CTSTM&nbs