拓撲排序:對有向無環圖 (DAG) 的節點進行排序,使得對於任何 u 到 v 的有向邊,u 都會出現在 v 之前。
常見考題:課程先修安排、任務的先後順序。
寫法
計算每個節點的入度 (指向該節點的邊數),將入度為 0 的節點加入佇列中。從佇列中取出節點,並將相鄰節點的入度減 1,重複以上步驟,直到佇列為空。
例題
ZeroJudge:f167. m4a1-社團 Club (本題 100% 拓撲排序)
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main() {
int n, m, a, b; // n 為節點數,m 為邊數
cin >> n >> m;
vector<vector<int>> g(n); // 儲存圖的鄰接表
vector<int> indegree(n, 0); // 儲存每個節點的入度
while (m--) {
cin >> a >> b;
a--, b--; // 將節點編號轉成 zero-based
g[a].push_back(b);
indegree[b]++;
}
queue<int> q;
vector<int> ans;
for (int i = 0; i < n; i++) {
if (indegree[i] == 0) q.push(i);
}
while (!q.empty()) {
int now = q.front();
ans.push_back(now + 1); // 將結果轉換回 1-based
q.pop();
for (int i : g[now]) {
if (--indegree[i] == 0) q.push(i);
}
}
if (ans.size() != n) {
cout << "NO\n";
} else {
cout << "YES\n";
for (int i : ans) {
cout << i << '\n';
}
}
}