地址 https://www.acwing.com/problem/content/description/850/ios
題目描述
給定一個n個點m條邊的有向圖,圖中可能存在重邊和自環。算法
請輸出任意一個該有向圖的拓撲序列,若是拓撲序列不存在,則輸出-1。數組
若一個由圖中全部點構成的序列A知足:對於圖中的每條邊(x, y),x在A中都出如今y以前,則稱A是該圖的一個拓撲序列。spa
輸入格式
第一行包含兩個整數n和mcode
接下來m行,每行包含兩個整數x和y,表示點x和點y之間存在一條有向邊(x, y)。blog
輸出格式
共一行,若是存在拓撲序列,則輸出拓撲序列。排序
不然輸出-1。隊列
數據範圍
1≤n,m≤105ip
樣例ci
輸入樣例: 3 3 1 2 2 3 1 3 輸出樣例: 1 2 3
算法1
拓撲排序流程爲BFS 流程以下
1 首先找到第一個入度爲0 的點 放入待處理隊列,記錄答案拓撲數組中 拓撲的必要條件
2 而後從該點鏈接的各個點 作如下操做:
2.1 刪除該邊後,查看從該點鏈接的的點的入度
2.2 若是入度爲0 那麼該點放入待處理隊列,記錄答案拓撲數組中, 再次進行BFS 直到待處理隊列爲空
C++ 代碼
#include <iostream> #include <iostream> #include <vector> #include <queue> using namespace std; int n, m; vector<vector<int>> outvec(100010, vector<int>()); //入度記錄 vector<int> invec(100010, 0);; //出度記錄 int main() { cin >> n >> m; for (int i = 0; i < m; i++) { int start; int end; cin >> start >> end; invec[end]++; outvec[start].push_back(end); } queue<int> q; for (int i = 1; i <= n; i++) { //找到第一個入度爲0的點 if (invec[i] == 0) { q.push(i); break; } } vector<int> ret; while (!q.empty()) { int idx = q.front(); q.pop(); ret.push_back(idx); //抹掉這個點的全部出度邊 與入度計數 for (auto& e : outvec[idx]) { if (e != -1) { invec[e]--; //該點入度減1 if (invec[e] == 0) { q.push(e); } e = -1; //抹掉該邊 } } } if(ret.size() == n) for (auto& e : ret) { cout << e << " "; } else cout << -1; return 0; } 做者:defddr 連接:https://www.acwing.com/solution/acwing/content/4196/ 來源:AcWing 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。