搜索与图论-有向图的拓扑序列

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

一、有向图的拓扑序列

  • 有向图的拓扑序列就是图的广度优先遍历的一个应用。

1. 拓扑序列

  • 若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。(起点在终点的前面)
  • 拓扑序列是针对有向图,无向图是没有拓扑序列的。
  • 有向无环图一定是拓扑序列,有向有环图一定不是拓扑序列。
  • 例如下图,由于 c 指向了 a ,所以该图不是拓扑序列。

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

  • 同样的例子,由于 d 指向了 b ,所以该图也不是拓扑序列。

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

2. 拓扑排序

  • 入度是指被其他点指向的数量。
  • 出度是指指向其他点的数量。
  • 举例说明:

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

  • 由上图可知,a 指向 b 和 c ,b 被 a 指向,并且指向 c ,c 被 a 和 b 指向。
  • 因此,a、b、c 的入度和出度分别为:
节点 入度 出度
a 0 2
b 1 1
c 2 0
  • 因此,所有入度为 0 的点都可以作为起点。

3. 如何进行拓扑排序

  • 一个有向图,如果图中有入度为 0 的点,就把这个点删掉,同时也删掉这个点所连的边。
  • 一直进行上面处理,如果所有点都能被删掉,则这个图可以进行拓扑排序。
  • 一个拓扑序列可以有多种输出方式。
  • 举例说明:

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

  • 开始时,图是这样的状态,发现 A 的入度为 0,所以删除 A 和 A 上所连的边,结果如下图:

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

  • 这时发现 B 的入度为 0,C 的入度为 0,所以删除 B 和 B 上所连的边、 C 和 C 上所连的边,结果如下图:

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

  • 这时发现 D 的入度为 0,所以删除 D 和 D 上所连的边(如果有就删),结果如下图:

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

  • 这时整个图被删除干净,所有能进行拓扑排序。
  • 对上述过程的实现,可以通过 queue 队列实现,入队的点的顺序就是拓扑序列

4. 拓扑排序具体实现详见例题有向图的拓扑序列

二、有向图的拓扑序列例题——有向图的拓扑序列

题目描述

给定一个 n 个点 m 条边的有向图,点的编号是 1 到 n,图中可能存在重边和自环。
请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。
若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。

输入格式

第一行包含两个整数 n 和 m。
接下来 m 行,每行包含两个整数 x 和 y,表示存在一条从点 x 到点 y 的有向边 (x,y)。

输出格式

共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。
否则输出 −1。

数据范围

1 ≤ n,m ≤ 1e5

输入样例

3 3
1 2
2 3
1 3

输出样例

1 2 3文章来源地址https://www.toymoban.com/news/detail-790079.html

具体实现

1. 样例演示

  • 输入 n=3 和 m=3 。表示一个有 3 个点,3 条边。
  • 从 1 指向 2 。
  • 从 2 指向 3 。
  • 从 1 指向 3 。
  • 如下图所示。
    有向图的拓扑序列,算法与数据结构,图论,算法,数据结构

2. 实现思路

  • 首先记录各个点的入度。
  • 然后将入度为 0 的点放入队列。
  • 将队列里的点依次出队列,然后找出所有出队列这个点发出的边,删除边,同时边的另一侧的点的入度 -1。
  • 如果所有点都进过队列,则可以拓扑排序,输出所有顶点。否则输出 -1,代表不可以进行拓扑排序。

3. 代码注解

  • int h[N], e[N], ne[N], idx;表示邻接表的存储方式。
  • int d[N];表示点的入度。
  • int q[N];表示队列。
  • if(d[j]==0);如果点 j 的入度为零了,就将点 j 入队。
  • return tt==n-1;表示如果 n 个点都入队了话,那么该图为拓扑图,返回 true ,否则返回 false 。
  • 其他注解在实现代码当中体现。

4. 实现代码

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;

int n, m;
int h[N], e[N], ne[N], idx;  
int d[N];
int q[N];

void add(int a, int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx ++;
}

//返回布尔序列是否存在, 若存在,则存储在q数组中
bool topsort()
{
    int hh = 0;
    int tt = -1;

    //遍历每一个节点, 入度为零则入队
    for (int i = 1; i <= n; i ++ )
    {
        if (!d[i])
        {
            tt ++;
            q[tt] = i;
        }
    }

    while (hh <= tt)
    {
        //队列不空,则取出头节点
        int t = q[hh];
        hh ++;

        //遍历头节点的每一个出边
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (-- d[j] == 0)
            {
                tt ++; 
                q[tt] = j;
            }
        }
    }

    return tt == n - 1;
}

int main()
{
    cin >> n >> m;
    
    memset(h, -1, sizeof h);

    for (int i = 0; i < m; i ++ )
    {
        int a, b;
        cin >> a >> b;
        add(a, b);

        d[b] ++ ;
    }

    if (!topsort()) 
    {
        puts("-1");
    }
    else
    {
        for (int i = 0; i < n; i ++ )
        {
           cout << q[i] << " ";
        }
        puts("");
    }
    system("pause");
    return 0;
}

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

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

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

相关文章

  • 【数据结构——有向图】有环无环判定、拓扑排序(DFS、BFS)

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

    2024年02月09日
    浏览(39)
  • 搜索与图论-拓扑序列

    为什么记录呢 因为不记录全忘了 虽然记了也不一定会看 有向无环图一定有拓扑序列 邮箱无环图 - 拓扑图 入度为0的点作为起点 入度为0的点入队列 枚举出边 t-j 删掉当前边,t-j . j的入度减1 判断j的入度是否为0,来判断是否加入队列 有环: 不存在入度为0的点

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

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

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

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

    2024年02月16日
    浏览(31)
  • 搜索与图论第五期 拓扑序列

    拓扑排序 拓扑排序是一种对有向无环图(Directed Acyclic Graph,简称DAG)进行的排序过程,目的是将图中所有的顶点按照发生事件的顺序排成一条线性序列。这种排序确保了图中任意两个相邻顶点之间至少有一条边相连,且在这条边的方向上,这条边的终点在前于起点。拓扑排

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

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

    2024年02月15日
    浏览(27)
  • 2023-04-09 有向图及相关算法

    有向图的的应用场景 社交网络中的关注 互联网连接 程序模块的引用 任务调度 学习计划 食物链 论文引用 无向图是特殊的有向图,即每条边都是双向的 改进Graph和WeightedGraph类使之支持有向图 Graph类的改动 WeightedGraph类的改动 有些问题,在有向图中不存在,或者我们通常不考

    2024年02月05日
    浏览(29)
  • 有向图的强连通分量算法

    有向图的强连通分量算法 强连通分量定义 在有向图中,某个子集中的顶点可以直接或者间接互相可达,那么这个子集就是此有向图的一个强连通分量,值得注意的是,一旦某个节点划分为特定的强连通分量后,此顶点不能在其它子树中重复使用,隐含了图的遍历过程和极大

    2024年02月06日
    浏览(42)
  • 【算法基础:搜索与图论】3.3 拓扑排序

    https://oi-wiki.org/graph/topo/ 本文主要学习拓扑排序相关知识。 拓扑排序的英文名是 Topological sorting。 拓扑排序要解决的问题是给一个 有向无环图 的 所有节点排序 。 我们可以拿大学每学期排课的例子来描述这个过程,比如学习大学课程中有:程序设计,算法语言,高等数学,

    2024年02月16日
    浏览(35)
  • 使用邻接矩阵实现有向图最短路径Dijkstra算法 题目编号:1136

    用邻接矩阵存储有向图,实现最短路径Dijkstra算法,图中边的权值为整型,顶点个数少于10个。 部分代码提示: #include #include using namespace std; const int MaxSize = 10; const int INF = 32767; class MGraph { public: MGraph(char a[], int n, int e); private: char vertex[MaxSize]; int arc[MaxSize][MaxSize]; int vertexNum,

    2024年02月01日
    浏览(66)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包