二十一、搜索与图论——拓扑序列(有向图)

这篇具有很好参考价值的文章主要介绍了二十一、搜索与图论——拓扑序列(有向图)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、基本思路

1、概念定义

  • 拓扑序列定义:

    • 若一个由图中所有点构成的序列 A满足:对于图中的每条边 (x,y),x在 A中都出现在 y之前,则称 A是该图的一个拓扑序列。
    • 人话:始终满足每条边的起点在终点前面,从前指向后。
  • 有向图拓扑序列,数据结构与算法,图论,java,算法,数据结构,散列表

  • 注意:如果在有向图中构成一个环,则必定无法构成拓扑结构,也可以证明有向无环图一定存在拓扑序列,即有向无环图=拓扑图

  • 入度:对一个节点而言,有多少条边指向自己。
  • 出度:对一个节点而言,有多少条边指向外面。

有向图拓扑序列,数据结构与算法,图论,java,算法,数据结构,散列表

二、拓扑序列模板

    1. 因为拓扑序列都是从前指向后面的,因此当前入度为0的点都可以当做是起点。
    1. 入度为0,意味着没有任何一个点在我面前,可以放在最前面的位置。
    1. 每次遍历完之后,就可以让 入度-1,表示前面指向他的确定了一个,直到为0 ,就可以加入序列,这就代表着后面再也没有指向这个节点的了。
// 伪代码
queue <--- 所有入度为0的点
while(queue 不空){
	t = 队头;
	枚举t的所有出边(t ---> j){
		j = e[i];
		删掉t ---> j这条边,即入度 d[j]--;
		if (d[j] == 0){			// 此时 j 的入度为了 0 ,则可以放在最前面去了
			queue <--- j;		// 入队
		}
	}
}
拓扑排序 —— 模板题 AcWing 848. 有向图的拓扑序列
时间复杂度 O(n+m)	n 表示点数,m 表示边数
bool topsort()
{
    int hh = 0, tt = -1;

    // d[i] 存储点i的入度
    for (int i = 1; i <= n; i ++ )
        if (!d[i])
            q[ ++ tt] = i;

    while (hh <= tt)
    {
        int t = q[hh ++ ];

        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (-- d[j] == 0)
                q[ ++ tt] = j;
        }
    }

    // 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。
    return tt == n - 1;
}

  • 若存在环,则找不到一个入度为 0 的点,没有突破口,无法入队。一个无环图,一定存在一个入度为0的点。

三、例题题解

有向图拓扑序列,数据结构与算法,图论,java,算法,数据结构,散列表文章来源地址https://www.toymoban.com/news/detail-767398.html

// java题解实现
import java.util.*;

public class Main{
    static int N = 100010;
    static int[] e = new int[N];
    static int[] ne = new int[N];
    static int[] h = new int[N];
    static int idx = 0;
    static int hh = 0;
    static int tt = -1;
    static int[] q = new int[N];
    static int[] d = new int[N];                // 表示入度大小,为了后面进行入度逐渐减小做准备
    static int n,m;
    
    static void add(int a, int b){
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }
    
    static boolean topsort(){
        
        for(int i = 1; i <= n; i++){        // 首先将入度为0的节点加入队列中
            if(d[i] == 0){
                q[++tt] = i;
            }
        }
        
        while(hh <= tt){
            int temp = q[hh++];             // 此处仅仅是对所控制的队列进行了首节点后移
            
            for(int i = h[temp]; i != -1; i = ne[i]){
                int j = e[i];               // 遍历当前队列节点能到达的节点
                d[j] --;                    // 有点指向,那必然不为0,遍历过去之后,就可以排除这个点指向了

                if(d[j] == 0){              // 如果入度后面为0了,说明没有点指向他了
                    q[++tt] = j;             // 入度为0了,后面的遍历没有指向他的了,所以可以加入队列了
                }
            }
        }
        
        return tt == n - 1;                  // 判断是不是队列已经将n个节点存在q中了,因为q从0开始存储的
    }

    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        
        n = in.nextInt();
        m = in.nextInt();
        
        for(int i = 0; i < N; i++){
            h[i] = -1;
            d[i] = 0;
        }
        
        for(int i = 0; i < m; i++){
            int a = in.nextInt();
            int b = in.nextInt();
            add(a, b);
            d[b]++;                         // 有节点指向 b故此需要进行入度+1
        }
        
        if(topsort()){
            for(int i = 0; i < n; i++){
                System.out.print(q[i] + " ");       // 尽管其中的hh指针已经移到后面,但是队列中始终存储着序列
            }
        }else{
            System.out.println("-1");
        }
        
    }
}

到了这里,关于二十一、搜索与图论——拓扑序列(有向图)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 搜索与图论(一)(深搜,广搜,树与图的存储遍历,拓扑排序)

    往深里搜,搜到叶子结点那里,回溯,到可以继续到叶子结点深搜的位置。 1、回溯一定要恢复现场 2、定义一个与当前递归层数有关的终止条件(题目要求的东西) 3、每层都用循环判断是否存在可以dfs的路 输出数字组合 全排列的思想解决n皇后问题,用三个bool数组描述限制

    2024年02月19日
    浏览(34)
  • 有向图的拓扑排序

    拓扑排序 。任意给定一个有向图,设计一个算法,对它进行拓扑排序。拓扑排序算法思想:a.在有向图中任选一个没有前趋的顶点输出;b.从图中删除该顶点和所有以它为尾的弧;c.重复上述a、b,直到全部顶点都已输出,此时,顶点输出序列即为一个拓朴有序序列;或者直到

    2024年02月09日
    浏览(34)
  • 2023-8-29 有向图的拓扑排序

    题目链接:有向图的拓扑排序

    2024年02月11日
    浏览(28)
  • 教学计划编制问题(数据结构 有向图 拓扑排序)

     本文对以下教学计划编制问题的解决作出实现,主要使用c语言(带一点cpp),开发环境为codeblocks 17.12,希望对各位读者有所帮助。(源码和数据文件可在主页获取,同时还有使用视频文件压缩包,数据文件需要和exe在同一目录下,结合某读者的意见同时放到github了 ) 地址如下

    2024年02月09日
    浏览(38)
  • 【数据结构——有向图】有环无环判定、拓扑排序(DFS、BFS)

    有向图(Directed Graph),也被称为有向图形或方向图,是一种图的类型。在有向图中,图中的边具有方向,从一个顶点指向另一个顶点。 在有向图中,每个顶点表示一个实体,而有向边则表示实体之间的关系或连接。这种有方向性的边表明了连接的起点和终点之间的单向关系

    2024年02月09日
    浏览(39)
  • 二十九、搜索与图论——克鲁斯卡尔算法(Kruskal 算法,稀疏图)

    解决问题: 多个城市中铺公路,使城市之间可以相互联通,问如何才能让铺设公路的长度最短——铺设的路径即为最小生成树。 思想: 从小到大枚举每条边,从小到大试图将每条边假如生成树,只要这条边对应的两个点不在一个集合,则把这条边加到集合中来。 主要面对的

    2024年02月05日
    浏览(35)
  • 第三章 图论 No.9有向图的强连通与半连通分量

    连通分量是无向图的概念,yxc说错了,不要被误导 强连通分量:在一个有向图中,对于分量中的任意两点u,v,一定能从u走到v,且能从v走到u。强连通分量是一些点的集合,若加入其他点,强连通分量中的任意两点就不能互相递达 半连通分量:在一个有向图中,对于分量中

    2024年02月13日
    浏览(32)
  • Matlab论文插图绘制模板第90期—带权重的有向图/图论图/网络图

    在之前的文章中,分享了Matlab 有向图 的绘制模板: 进一步,如果我们想 标注有向图的每条边的权重,或者直接用线条的粗细来表示权重 ,该怎么操作呢? 先来看一下成品效果: 特别提示:本期内容『数据+代码』已上传资源群中,加群的朋友请自行下载。有需要的朋友可

    2024年02月16日
    浏览(31)
  • 试基于图的深度优先搜索策略写一算法,判别以邻接表方式存储的有向图中是否存在由顶点a到顶点b的路径

    试基于图的深度优先搜索策略写一算法,判别以邻接表方式存储的有向图中是否存在由顶点a到顶点b的路径,注意a!=b(必须严格按照样例进行输入输出,先输入图的顶点数和弧数,并依次输入弧的相关信息,最后输入要判断的两个顶点的信息) 样例如下: 输入: 5 4 2 4 2 1

    2024年02月15日
    浏览(27)
  • 搜索与图论 - 搜索与图在算法中的应用【中】

    目录 迪杰斯特拉算法Dijkstra  Dijkstra求最短路 I Dijkstra求最短路 II 贝尔曼-福特算法 bellman-ford 有边数限制的最短路 SPFA算法 spfa求最短路  spfa判断负环 Floyd Floyd求最短路   该算法不能存在负权边 思路: 初始化距离数组, dist[1] = 0, dist[i] = inf; for n次循环 每次循环确定一个min加

    2023年04月08日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包