我將描述問題的多對數解法。我們來介紹一些定義。我們將表示:
- 集圖的頂點由
V
,由E
設定圖的邊緣,並通過T
設置MST邊。
- 頂點之間的圖形的邊緣
v
和u
由{v, u}
所示。
- 邊緣的重量
e
由W(e)
和MST的重量爲W(T)
。
讓我們考慮功能MaxEdge(v, u)
,這等於與v
和u
之間的簡單路徑上的最大權重的邊緣屬於T
。如果有幾個最大重量的邊緣MaxEdge(v, u)
可以等於它們中的任何一個。
要找到第二個最好的MST,我們需要找到這樣的邊緣x = {p, q}
,即:
x
不屬於T
。
- 功能
W(x) - W(MaxEdge(p, q))
是儘可能最小。
這是可能的,以證明所述第二最佳MST可以通過從T
除去MaxEdge(p, q)
,然後加入到x = {p, q}
T
來構造。
現在我們來構建一個數據結構,它將能夠在O(log|V|)
中計算MaxEdge(p, q)
。
我們爲樹T
(它可以是任何頂點)選擇一個根。我們將調用頂點v
與根之間的簡單路徑中的邊數 - 頂點的深度v
,並將其表示爲Depth(v)
。我們可以通過depth first search計算O(|V|)
中所有頂點的Depth(v)
。
讓我們來計算兩個功能,這將有助於我們計算MaxEdge(p, q)
:
Parent(v, i)
,這等於說是父母的頂點頂點v
的(可能是非直接的母公司)與深度等於Depth(v) - 2^i
。
MaxParentEdge(v, i)
,等於MaxEdge(v, Parent(v, i))
。
兩者都可以通過記憶在O(|V|log|V|)
中的遞歸函數來計算。
// Assumes that 2^i <= Depth(v)
Vertex Parent(Vertex v, Vertex i) {
if (i == 0) return direct_parent[v];
if (Memorized(v, i)) return memorized_parent[v][i];
memorized_parent[v][i] = Parent(Parent(v, i - 1), i - 1);
return memorized_parent[v][i];
}
Edge MaxParentEdge(Vertex v, Vertex i) {
if (i == 0) return Edge(v, direct_parent[v]);
if (Memorized(v, i)) return memorized_parent_edge[v][i];
Edge e1 = MaxParentEdge(v, i - 1);
Edge e2 = MaxParentEdge(Parent(v, i - 1), i - 1);
if (W(e1) > W(e2)) {
memorized_parent_edge[v][i] = e1;
} else {
memorized_parent_edge[v][i] = e2;
}
return memorized_parent_edge[v][i];
}
在我們準備計算MaxEdge(p, q)
之前,我們來介紹最終的定義。 Lca(v, u)
將表示根樹T
中的頂點v
和u
的lowest common ancestor。有許多衆所周知的數據結構允許在O(log|V|)
甚至O(1)
中計算Lca(v, u)
查詢(您可以在Wikipedia找到文章列表)。
爲了計算MaxEdge(p, q)
,我們將分p
和q
之間的路徑分爲兩個部分:從p
到Lca(p, q)
,從Lca(p, q)
到q
。這些部分中的每一個看起來像從頂點到其父母的路徑,因此我們可以使用我們的Parent(v, i)
和MaxParentEdge(v, i)
函數來計算這些部分的MaxEdge
。
Edge MaxEdge(Vertex p, Vertex q) {
Vertex mid = Lca(p, q);
if (p == mid || q == mid) {
if (q == mid) return QuickMaxEdge(p, mid);
return QuickMaxEdge(q, mid);
}
// p != mid and q != mid
Edge e1 = QuickMaxEdge(p, mid);
Edge e2 = QuickMaxEdge(q, mid);
if (W(e1) > W(e2)) return e1;
return e2;
}
Edge QuickMaxEdge(Vertex v, Vertex parent_v) {
Edge maxe = direct_parent[v];
string binary = BinaryRepresentation(Depth(v) - Depth(parent_v));
for (int i = 0; i < binary.size(); ++i) {
if (binary[i] == '1') {
Edge e = MaxParentEdge(v, i);
if (W(e) > W(maxe)) maxe = e;
v = Parent(v, i);
}
}
return maxe;
}
基本上起作用QuickMaxEdge(v, parent_v)
確實長度2^i
的跳躍,以覆蓋parent_v
和v
之間的距離。在跳轉期間,它使用預先計算的值MaxParentEdge(v, i)
來更新答案。
考慮到MaxParentEdge(v, i)
和Parent(v, i)
是預先計算的,MaxEdge(p, q)
作品O(log|V|)
,這使我們的O(|E|log|V|)
解決最初的問題。我們只需要遍歷所有不屬於T
的邊,併爲它們中的每一個計算W(e) - MaxEdge(p, q)
。
如果你可以添加一個psedocode,它會更合適,人們可以很容易地理解你的答案。 – arunmoezhi
請你詳細說明爲什麼這個工程? – Math