模板:拓撲排序

拓撲排序

定義

將一個有向無環圖的所有頂點排成一個線性序列,滿足所有單向邊都由序號小的頂點指向序號大的頂點,這就是拓撲排序。

思路

計算所有頂點的入度,將入度爲00的頂點排在前面,即序號較小的位置,然後刪去這些頂點以及連接的邊,再從剩下的頂點中選取入度爲00的頂點排序,不斷循環直到所有頂點均分配好序號。因爲當頂點被分配序號時入度爲00,即所有指向該頂點的邊均來自序號更小的頂點,所以按序號形成的線性序列滿足拓撲排序的條件。由於有向圖無環,故在循環中不可能出現所有頂點的入度都大於00的情況。

時間複雜度

設單向邊的數量爲mm,則時間複雜度爲O(m)O(m)

測試

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]);
      }
    }
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章