acwing 848 有向图的拓扑序列

老子叫甜甜 提交于 2019-11-28 18:07:31

地址 https://www.acwing.com/problem/content/description/850/

题目描述
给定一个n个点m条边的有向图,图中可能存在重边和自环。

请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出-1。

若一个由图中所有点构成的序列A满足:对于图中的每条边(x, y),x在A中都出现在y之前,则称A是该图的一个拓扑序列。

输入格式
第一行包含两个整数n和m

接下来m行,每行包含两个整数x和y,表示点x和点y之间存在一条有向边(x, y)。

输出格式
共一行,如果存在拓扑序列,则输出拓扑序列。

否则输出-1。

数据范围
1≤n,m≤105

样例

输入样例:
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
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!