zoukankan      html  css  js  c++  java
  • 拓扑序

    通俗解释拓扑序就是一个包含依赖关系的序列
    假设做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;
    }
    
  • 相关阅读:
    Linux下制作和使用静态库和动态库
    C语言的内存管理
    C语言柔性数组
    大小端模式
    C位域操作
    C/C++字节对齐
    C/C++指针
    Linux之Socket编程
    VSCode配置FTP
    GCC的编译过程和链接
  • 原文地址:https://www.cnblogs.com/G-H-Y/p/14799176.html
Copyright © 2011-2022 走看看