有向图的拓扑序列

题目

思路

这里只给一些疑惑上的解答:

  • 为什么不删除边?
    • 这里是等效的,因为入度数减少1,且起点从队列弹出了不会再进入
  • 为什么可以直接从q里找序列,不会出现点重复进入吗?
    • 点进入的条件是入度为0,此时没有边的终点是该点了,这个点不会再出现(当然出现了了入度要变成-1,嘻嘻),所以不会再次进入队列
  • 为什么初始化一次要进入多个0入度点
    • 过程中变成入度为0,是这个点最后一次出现的状态,之后这个点不会再出现了
    • 最开始为0,这个点就根本不会被遍历到,只能靠开始压入

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10, M = N;
int h[N], e[M], ne[M], idx;
int q[N], hh = 0, tt = -1;
int ind[N], cnt;
int n, m;
void add(int a, int b)  // 添加一条边a->b
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void topo()
{
    for(int i = 1; i <= n; i++)
        if(ind[i] == 0) q[++tt] = i;
    
    while(hh <= tt)
    {
        int u = q[hh++]; cnt++;
        for(int i = h[u]; ~i; i = ne[i])
        {
            int j = e[i];
            ind[j]--;
            if(ind[j] == 0) q[++tt] = j;
        }
    }
    
    if(cnt == n)
    {
        for(int i = 0; i < n; i++)
            cout << q[i] << ' ';
    }
    else cout << -1;
}
int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    for(int i = 1; i <= m; i++)
    {
        int a, b;
        cin >> a >> b;
        ind[b]++;
        add(a, b);
    }
    
    topo();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值