拓撲排序
定義
將一個有向無環圖的所有頂點排成一個線性序列,滿足所有單向邊都由序號小的頂點指向序號大的頂點,這就是拓撲排序。
思路
計算所有頂點的入度,將入度爲的頂點排在前面,即序號較小的位置,然後刪去這些頂點以及連接的邊,再從剩下的頂點中選取入度爲的頂點排序,不斷循環直到所有頂點均分配好序號。因爲當頂點被分配序號時入度爲,即所有指向該頂點的邊均來自序號更小的頂點,所以按序號形成的線性序列滿足拓撲排序的條件。由於有向圖無環,故在循環中不可能出現所有頂點的入度都大於的情況。
時間複雜度
設單向邊的數量爲,則時間複雜度爲
測試
POJ:2367
模板
#include <iostream>
using namespace std;
#include <cstring>
#include <queue>
#include <vector>
const int N = 2e5+10; // the maximal number
vector<int> edge[N]; // the directed edge of vertex
int order[N]; // the order of vertex
int indeg[N]; // the indegree of vertex
int n; // the number of vertex
void TP() {
// count the indegree
memset(indeg, 0, sizeof(indeg));
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < edge[i].size(); ++j) {
++indeg[edge[i][j]];
}
}
queue<int> q;
for (int i = 1; i <= n; ++i) {
if (indeg[i] == 0) {
q.push(i);
}
}
int pos = 1;
while (!q.empty()) {
int curr = q.front();
order[curr] = pos++; // allocate the order
q.pop();
for (int i = 0; i < edge[curr].size(); ++i) {
--indeg[edge[curr][i]]; // decrease the indegree
if (indeg[edge[curr][i]] == 0) {
q.push(edge[curr][i]);
}
}
}
}