[英]Topological Sort with Grouping
好的,所以在拓撲排序中,取決於輸入數據,通常有多個正確的解決方案,可以對圖表進行“處理”,以便所有依賴關系都在“依賴”它們的節點之前。 但是,我正在尋找一個稍微不同的答案:
假設以下數據: a -> b
和c -> d
( a
必須出現在b
和c
必須來到之前d
)。
只有這兩個約束我們有多個候選解決方案:( abcd
, acdb
, cabd
等)。 但是,我正在尋找創建一種“分組”這些節點的方法,以便在處理組之后,下一組中的所有條目都會依賴它們的依賴關系。 對於上面假設的數據,我會尋找像(a, c) (b, d)
這樣的分組。 在每個組內不要緊何種順序節點被處理( a
前c
或b
之前d
等,並反之亦然)只是只要1組(a, c)
完成前的任何組2的(b, d)
正在處理中。
唯一額外的問題是每個節點應該盡可能在最早的組中。 考慮以下:
a -> b -> c
d -> e -> f
x -> y
(a, d) (b, e, x) (c, f, y)
的分組方案在技術上是正確的,因為x
在y
之前,更優化的解是(a, d, x) (b, e, y) (c, f)
因為在組2中具有x
意味着x
依賴於組1中的某個節點。
關於如何做到這一點的任何想法?
編輯:我想我設法將一些解決方案代碼拼湊在一起。 感謝所有幫助過的人!
// Topological sort
// Accepts: 2d graph where a [0 = no edge; non-0 = edge]
// Returns: 1d array where each index is that node's group_id
vector<int> top_sort(vector< vector<int> > graph)
{
int size = graph.size();
vector<int> group_ids = vector<int>(size, 0);
vector<int> node_queue;
// Find the root nodes, add them to the queue.
for (int i = 0; i < size; i++)
{
bool is_root = true;
for (int j = 0; j < size; j++)
{
if (graph[j][i] != 0) { is_root = false; break; }
}
if (is_root) { node_queue.push_back(i); }
}
// Detect error case and handle if needed.
if (node_queue.size() == 0)
{
cerr << "ERROR: No root nodes found in graph." << endl;
return vector<int>(size, -1);
}
// Depth first search, updating each node with it's new depth.
while (node_queue.size() > 0)
{
int cur_node = node_queue.back();
node_queue.pop_back();
// For each node connected to the current node...
for (int i = 0; i < size; i++)
{
if (graph[cur_node][i] == 0) { continue; }
// See if dependent node needs to be updated with a later group_id
if (group_ids[cur_node] + 1 > group_ids[i])
{
group_ids[i] = group_ids[cur_node] + 1;
node_queue.push_back(i);
}
}
}
return group_ids;
}
標記級別值為0的所有根節點。標記級別值為parent + 1的所有子節點。 如果正在重新訪問節點,即它已經分配了一個級別值,請檢查先前分配的值是否低於新值。 如果是這樣,請使用更高的值更新它並將它們傳播給后代。
現在,你有多個組,因為有獨特的級別標簽0 ... K.
我最近實現了這個算法。 我從你展示的方法開始,但它沒有擴展到超過2億個節點的圖形。 我最終得到的解決方案基於此處詳述的方法 。
您可以將其視為計算每個節點的高度,然后結果是給定高度的每個節點的一組。
考慮圖表:
A - > X.
B - > X.
X - > Y.
X - > Z.
所以期望的輸出是(A,B),(X),(Y,Z)
基本方法是找不到任何東西使用它(本例中為A,B)。 所有這些都在0高度。
現在從圖中刪除A和B,找到任何現在沒有使用它的東西(在這個例子中現在是X)。 所以X的高度為1。
從圖中刪除X,找到任何現在沒有使用它的東西(在本例中為Y,Z)。 所以Y,Z的高度為2。
您可以通過實現以下事實進行優化:您不需要為所有內容存儲雙向邊緣或實際從圖形中刪除任何內容,您只需要知道指向節點的事物數量以及您知道的節點數量。下一個高度。
所以對於這個例子的開頭:
當您訪問節點時,減少它指向的每個節點的數量,如果該數字變為零,則您知道該節點處於下一個高度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.