acwing 848 有向圖的拓撲序列

地址 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
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索