• 浅谈拓扑排序


    今天来讲讲拓扑排序

    度娘告诉我

    对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

    维基百科又和我说

    图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该的一个拓扑排序英语:Topological sorting)。

    1. 每个顶点出现且只出现一次;
    2. 若A在序列中排在B的前面,则在图中不存在从B到A的路径

    也可以定义为:拓扑排序是对有向无环图的顶点的一种排序,它使得如果存在一条从顶点A到顶点B的路径,那么在排序中B出现在A的后面[1]

    想了解的自己去找,我就说这么多了。

    下面步入正题。

    看下面的样例。

    不过要先说明一下输入格式:第一行一个整数N,之后的N行,每行若干个以0为结尾的整数。

    表示第 i 个节点向这些个节点都有一条(有向)边。

    那么这张图的拓扑排序就是2 4 5 3 1当然可能并不唯一。

    下图是他拓扑排序后变得更加直观的图

    那么这个拓扑排序是如何实现的呢。

    下面我们就来看看。

    首先定义一个indgr数组,表示每个点的入度(就是有几条边是指向他的)。

    定义一个栈。先将所有入度为0的点入栈。然后每次都把栈顶元素输出,并且弹出记录下来,还要用一个cnt记录输出次数。输出之后,把与相连的点的入度-1,如果-1之后这个点的入度变为了0,那么就将这个点入栈,重复此操作,直到所有的点都被输出一遍,也就是说cnt==n的时候就可以结束程序了。

    下面是代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <stack>
    
    using namespace std;
    
    stack<int> S;
    int n, cnt;
    int son, tot[105];
    int indgr[108];
    int ed[105][105];
    
    int main() {
        scanf("%d", &n);
        for(int i=1; i<=n; i++) {
            while(scanf("%d", &son) == 1) {
                if(son == 0) {
                    break;
                }
                ed[i][++tot[i]] = son;
                indgr[son]++;
            }
        }
        for(int i=1; i<=n; i++) {
            if(indgr[i] == 0) {
                S.push(i);
            }
        }
        while(cnt != n) {
            int k = S.top();
            printf("%d ", k);
            cnt++;
            S.pop();
            for(int i=1; i<=tot[k]; i++) {
                indgr[ed[k][i]]--;
                if(indgr[ed[k][i]] == 0) {
                    S.push(ed[k][i]);
                }
            }
        }
        return 0;
    }
    作者:wlz
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    解决:oracle+myBatis ResultMap 类型为 map 时返回结果中存在 timestamp 时使用 jackson 转 json 报错
    jackson @ResponseBody 处理日期类型的字段
    spring 中 InitializingBean 接口使用理解
    idea 中如何生成类图
    阿里云centOS 重启后 重启应用步骤
    日期类型 通过JOSN.stringify 后时间倒退8小时问题
    centOS7 下 安装mysql8.x
    Linux下卸载mysql8.x版本
    服务器上 MySql 8.0.16创建远程连接账号、获取初始密码、修改密码、重启命令等
    vue中读取excel中数据
  • 原文地址:https://www.cnblogs.com/bljfy/p/8729163.html
Copyright © 2020-2023  润新知