拓扑序

通俗解释拓扑序就是一个包含依赖关系的序列
假设做C之前必须做完B,做B之前必须做完A,拓扑序就是ABC

实现思路

维护各个节点的入度,将入度为0的节点入队
将入度为0的节点的所有周边节点的入度减1,并将入度为0的节点入队
当队列为空时,过程结束。
若图中存在环路,则进入队列的元素个数<总节点个数,由此可判断图中是否存在环

易错点

拓扑序只能验证图中是否存在环,而无法对图的连通性做出验证

代码实现

#include <iostream>
#include <cstring>

using namespace std;

const int N = 1e5 + 10;

int n, m;
int head[N], e[N], ne[N], idx;
int in[N], q[N];

void insert(int a, int b)
{
    e[idx] = b;
    ne[idx] = head[a];
    head[a] = idx ++;
}
bool topsort()
{
    int hh = 0, tt = -1;
    
    for (int i = 1; i < n; ++ i)
        if (!in[i]) q[++ tt] = i;
    
    while (hh <= tt)
    {
        int t = q[hh ++];
        for (int i = head[t]; i != -1; i = ne[i])
        {
            int c = e[i];
            -- in[c];
            if (!in[c]) q[++ tt] = c;
        }
    }
    
    return tt == n - 1; // 如果存在拓扑序列也就是不存在环路,那么所有点一定都可以被访问到,由于tt从0开始,n个点tt最大为n-1
}
int main()
{
    memset(head, -1, sizeof head); // 初始化链表头需要在更新链表之前进行
    cin >> n >> m;
    for (int i = 0; i < m; ++ i) 
    {
        int a, b;
        cin >> a >> b;
        insert(a, b);
        ++ in[b];
    }
    
    if (!topsort()) cout << -1 << endl;
    else 
    {
        // 非常巧妙的是如果存在拓扑序列,那么它正好就是队列中的顺序
        for (int i = 0; i < n; ++ i) cout << q[i] << ' ';
        cout << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/G-H-Y/p/14799176.html