拓扑排序(有向图的拓扑排序)

拓扑序列是针对有向图。拓扑序列例如:1-->2、2-->3、1-->3,则序列[1 2 3]是一个拓扑序列,因为满足起点在终点的前面。所以存在环的一定没有拓扑序列,而有向无环图一定存在拓扑序列,因此有向无环图又称为拓扑图。

有向无环图的求法:

入度指有多少条边指向自己,出度是有多少条边出去,因此3的入度为2,出度为0。

  1. 将所有入度为0的点入队。所有入度为0的点都可以作为起点
  2. 进行宽搜。t作为队头
  3. 枚举t的所有出边
  4. 删掉t

题目:

答案:

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n, m;
int h[N], e[N], ne[N], idx;
int d[N];  //存入度
int q[N];  //队列

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

bool topsort()
{
    int hh = 0, tt = -1;  //队头队尾

    for (int i = 1; i <= n; i ++ )  //从前往后遍历所有的点,把所有入度为0的点插入到队列中去
        if (!d[i])
            q[ ++ tt] = i;

    while (hh <= tt)  //队列不空
    {
        int t = q[hh ++ ];   //取出队头

        for (int i = h[t]; i != -1; i = ne[i])  //枚举t的所有出边
        {
            int j = e[i];  //找到出边
            if (-- d[j] == 0)  //入度减一删掉t,d[j]==0说明所有的点都已经放好了
                q[ ++ tt] = j;   //将j放到最前面,将让j入队(如果有环的话是无法入队的,因为一定不满足入度为0,而一个有向无环图一定存在至少一个入度为0的点)
        }
    }

    return tt == n - 1;  //判断是否所有的点都入队了
}

int main()
{
    cin>>n>>m;

    memset(h, -1, sizeof h);

    for (int i = 0; i < m; i ++ )
    {
        int a, b;
        cin>>a>>b;
        add(a, b);

        d[b] ++ ;  //插入一条边,更新一下入度
    }

    if (!topsort()) puts("-1");
    else     //如果存在拓扑序列就输出
    {
        for (int i = 0; i < n; i ++ ) cout<<q[i]<<" ";
        puts("");
    }

    return 0;
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值