• 拓扑排序


    在有向无环图(DAG,即 Directed Acyclic Graph)中,拓扑排序(Topological Sorting)是其顶点的线性排序,使得对于从顶点 \(u\) 到顶点 \(v\) 的每个有向边,在排序中 \(u\) 都在 \(v\) 之前。

    有向无环图(DAG)才有拓扑排序,非 DAG 图是没有拓扑排序这个概念的。

    例如,下面这个图,是一个 DAG,

    算法实现

    拓扑排序的实现非常之简单,下面介绍一个常用的实现算法 - 卡恩算法(Kahn's algorithm),

    1. 从 DAG 中选择一个没有前驱(即入度为 0)的顶点并输出;
    2. 从图中删除该顶点和所有以它为起点的有向边;
    3. 重复 1 和 2 直到当前的 DAG 为空或当前图中不存在无前驱的顶点为止。后一种情况说明该图中必然存在环,可以以此判断该图是否能生成拓扑排序序列。

    代码如下:

    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    int n;                /* 顶点数(<=100) */
    int m;                /* 边数 */
    int matrix[105][105]; /* 邻接矩阵 */
    int inDegree[105];    /* 入度 */
    
    void TopologicalSort() {
        int num = 0; /* 已被拓扑排序的顶点的个数 */
        queue<int> q;
    
        /* 找到所有入度为 0 的顶点,并入队列 */
        for (int i = 1; i <= n; ++i) {
            if (inDegree[i] == 0) {
                num++;
                inDegree[i]--;
                q.push(i);
                cout << i << " ";
            }
        }
    
        while (!q.empty()) {
            int u = q.front();
            q.pop();
    
            for (int v = 1; v <= n; ++v) {
                if (matrix[u][v]) {
                    inDegree[v]--;
                    if (inDegree[v] == 0) {
                        num++;
                        q.push(v);
                        cout << v << " ";
                    }
                }
            }
        }
    
        /* 说明有环 */
        if (num != n)
            cout << "有环,无法生成拓扑序列";
    
        cout << endl << endl;
    }
    
    int main() {
        while (true) {
            memset(matrix, 0, sizeof(matrix));
            memset(inDegree, 0, sizeof(inDegree));
    
            cout << "请输入顶点数(<=100):";
            cin >> n;
            cout << "请输入边数:";
            cin >> m;
    
            cout << "请输入 " << m << " 条有向边:" << endl;
            int u, v;
            for (int i = 0; i < m; ++i) {
                cin >> u >> v;
                matrix[u][v] = 1;
                inDegree[v]++;
            }
    
            cout << "拓扑序列为:";
            TopologicalSort();
        }
        return 0;
    }
    

    输出如下:

    请输入顶点数(<=100):5
    请输入边数:7
    请输入 7 条有向边:
    1 2
    1 4
    2 4
    2 3
    4 3
    3 5
    4 5
    拓扑序列为:1 2 4 3 5
    
    请输入顶点数(<=100):3
    请输入边数:3
    请输入 3 条有向边:
    1 2
    2 3
    3 1
    拓扑序列为:有环,无法生成拓扑序列
    

    参考

  • 相关阅读:
    Lambda表达式 For Android
    RxJava重温基础
    Asp.Net Core 依赖注入默认DI,Autofac注入
    Asp.Net Core2.0 基于QuartzNet任务管理系统
    Asp.Net Core 基于QuartzNet任务管理系统(这是一篇用来水的随笔)
    ADO.NET通用类库
    TripleDES加密解密
    ASP.NET Core的身份认证框架IdentityServer4--(4)添加第三方快捷登录
    ASP.NET Core的身份认证框架IdentityServer4--(3)令牌服务配置访问控制跟UI(可自定义路由)添加
    ASP.NET Core的身份认证框架IdentityServer4--(2)API跟WEB端配置
  • 原文地址:https://www.cnblogs.com/RioTian/p/13056589.html
Copyright © 2020-2023  润新知