ฅ(๑˙o˙๑)ฅ 大家好, 欢迎大家光临我的博客:面向阿尼亚学习
算法学习笔记系列持续更新中~


文章目录

  • 一、前言
  • 二、算法流程
  • 三、有向图的拓扑排序
  • 最后

一、前言

拓扑排序(Topological Sorting)
若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。

且该序列必须满足下面两个条件:

  • 每个顶点出现且只出现一次。
  • 若存在一条从顶点 x到顶点 y的路径,那么在序列中顶点 x 出现在顶点 y的前面。

拓扑排序只适用于 AOV网 (有向无环图)
若图中有环,则一定不存在拓扑序。
可以证明,一个有向无环图,一定存在一个拓扑序列。有向无环图,又被称为拓扑图

入度: 即有多少条边指向自己这个节点。

出度: 即有多少条边从自己这个节点指出去。


二、算法流程

算法流程:

  • 用队列来执行 ,初始化所有入度为0的顶点入队。

  • 主要由以下两步循环执行,直到不存在入度为 0 的顶点为止

  • 选择一个入度为 0 的顶点,并将它输出;
    删除图中从顶点连出的所有边。
    循环结束,

  • 若输出的顶点数小于图中的顶点数,则表示该图存在回路,即无法拓扑排序,

  • 否则,输出的就是拓扑序列 (不唯一)

模板如下:

1.数组模拟队列实现拓扑排序

bool topsort()
{int hh = 0, tt = -1;// in[i] 存储点i的入度for (int i = 1; i <= n; i ++ )// 将所有入度为0的点加入队列if (in[i]==0)top[ ++ tt] = i;while (hh <= tt){int t = top[hh ++ ];//找到入度为0的队头//遍历一下以t为头节点的的单链表,给每一个结点都要减去1,并再次找到入度为0的点for (int i = h[t]; i != -1; i = ne[i]){// 遍历 t 点的出边int j = e[i];if (-- in[j] == 0)//将入度减1,如果 j 入度为0,加入队列当中top[ ++ tt] = j;}}// 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。return tt == n - 1;
}

2.使用STL queue实现拓扑排序

bool topsort(){queue<int> q;int t;for(int i = 1;i <= n; ++i)// 将所有入度为0的点加入队列if(in[i] == 0) q.push(i);while(q.size()){t = q.front();//每次取出队列的首部top[cnt] = t;//加入到 拓扑序列中cnt ++; // 序列中的元素 ++q.pop();for(int i = h[t];i != -1; i = ne[i]){// 遍历 t 点的出边int j = e[i];in[j] --;// j 的入度 --if(in[j] == 0) q.push(j); //如果 j 入度为0,加入队列当中}}if(cnt < n) return 0;else return 1;}

时间复杂度 O(n+m), n表示点数,m表示边数

三、有向图的拓扑排序

给定一个 n 个点 m 条边的有向图,点的编号是 1 到 n,图中可能存在重边和自环。
请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。

思路
我们每次找到入读为0的点,然后把他插入到队列里,然后将这个点删除,这也就意味着这个点连接的下一个点(可能是多个)的入度就会减1。
这个时候,我们就进入了下一轮。
我们因为前面将一个点删除了,那么它指向的点的入度就会都减去1,所以,就会出现新的点的入度为0,这个点显然是因为它的入度小,所以它理所应当的排在拓扑序里面在第二位。当前面的一个点没有了被删除了,
那它就要首当其冲了。

和图的BFS思路很像,但是加了搜索的规则(即入度为零的先被搜索)可以看点这里

AC代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e5 + 10;
int e[N],ne[N],h[N],idx,in[N],n,m,top[N],cnt = 1;
// e,ne,h,idx 邻接表模板
// in 代表每个元素的入度
// top是拓扑排序的序列,cnt代表top中有多少个元素
void add(int a,int b){e[idx] = b; ne[idx] = h[a];h[a] = idx ++;
}
bool topsort(){queue<int> q;int t;for(int i = 1;i <= n; ++i)// 将所有入度为0的点加入队列if(in[i] == 0) q.push(i);while(q.size()){t = q.front();//每次取出队列的首部top[cnt] = t;//加入到 拓扑序列中cnt ++; // 序列中的元素 ++q.pop();for(int i = h[t];i != -1; i = ne[i]){// 遍历 t 点的出边int j = e[i];in[j] --;// j 的入度 --if(in[j] == 0) q.push(j); //如果 j 入度为0,加入队列当中}}if(cnt < n) return 0;else return 1;}
int main(){int a,b;cin >> n >> m;memset(h,-1,sizeof h);//给头节点赋值为-1;while(m--){cin >> a >> b;add(a,b);in[b] ++;// a -> b , b的入度++}if(topsort() == 0) cout << "-1";else {for(int i = 1;i <= n; ++i){cout << top[i] <<" ";}}return 0;
}

最后

莫言真理无穷尽,寸进自有寸进欢

【图论——第三讲】图的拓扑排序相关推荐

  1. 图论算法—图的拓扑排序介绍和Kahn算法原理解析以及Java代码的实现

    详细介绍了图的拓扑排序的概念,然后介绍了求拓扑序列的算法:Kahn算法的原理,最后提供了基于邻接矩阵和邻接表的图对该算法的Java实现. 阅读本文需要一定的图的基础,如果对于图不是太明白的可以看看这篇 ...

  2. 【图论】有向无环图的拓扑排序

    1. 引言 有向无环图(Directed Acyclic Graph, DAG)是有向图的一种,字面意思的理解就是图中没有环.常常被用来表示事件之间的驱动依赖关系,管理任务之间的调度.拓扑排序是对DA ...

  3. 有向无环图DAG 拓扑排序 代码解释

    目录: DAG定义 举例描述 实际运用 算法描述 算法实战 算法可视化 定义 在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(英语:Topological ...

  4. 第5-2课:图的拓扑排序

    拓扑排序常用来确定一个依赖关系集中.事物发生的顺序.一个典型的应用场景就是在项目管理或工程实施中安排各种生产活动的计划,在考虑各种活动的依赖关系的基础上,安排各种活动的开始时间,使得项目或工程能够以高 ...

  5. 数据结构-考研难点代码突破 (C++实现有向无环图的拓扑排序)

    文章目录 1. AOV网 2. 拓扑排序 C++代码 1. AOV网 AOV网∶若用DAG 图(有向无环图)表示一个工程,其顶点表示活动,用有向边<Vi,Vj>表示活动 Vi必须先于活动V ...

  6. 有向无环图的拓扑排序

    拓扑排序 对于一个有向无环图,我们可以这样确定一个图中顶点的顺序:  对于所有的u.v,若存在有向路径u-->v,则在最后的顶点排序中u就位于v之前.这样确定的顺序就是一个图的拓扑排序.     ...

  7. 数据结构与算法之-----图(拓扑排序)

    [​​​​​​​ 写在前面的话:本专栏的主要内容:数据结构与算法. 1.对于​​​​​​​初识数据结构的小伙伴们,鉴于后面的数据结构的构建会使用到专栏前面的内容,包括具体数据结构的应用,所使用到的数据 ...

  8. BUCT数据结构——图(拓扑排序、关键路径)

    文章目录 问题 A: 邻接矩阵存储的图,节点的出度和入度计算(附加代码模式) 问题 B: 算法7-12:有向无环图的拓扑排序 问题 C: 有向图是否存在环? 问题 D: 图-节点的最早发生时间 问题 ...

  9. 图的拓扑排序(AOV网络)

    文章目录 拓扑排序 概念 实现 邻接表(队列) 邻接矩阵(栈) 总结 源代码 邻接表 邻接矩阵 拓扑排序 概念 拓扑排序是对有向无环图的顶点的一种排序. AOV网络 : 在有向图中, 用顶点表示活动或 ...

  10. P6560 [SBCOI2020] 时光的流逝 (博弈,反向建图,拓扑排序

    洛谷P6560 [SBCOI2020] 时光的流逝 题意: 给定一个有向图(可能有环),给定起点和终点,两个人玩游戏,一人走一步,先到达终点的人赢或者先无法移动的人输 思路: 题解 因为是终点和叶子节 ...

最新文章

  1. 软件工程技术基础-(软件复用技术)
  2. 南航计算机硬件实验,南航80X86微机原理及接口技术实验指导书.pdf
  3. python conrurrent
  4. failed to launch: nice -n 0 $HADOOP_HOME/bin/spark-class org.apache.spark.deploy.worker.Worker
  5. 洛谷1091合唱队形
  6. 李国庆深夜发“15条真相”回应:关于原生家庭、同性恋、1.3亿...
  7. Bailian2899 Bailian3242 矩阵交换行【矩阵】
  8. 高岭土吸附阳离子_高岭石对金属阳离子的吸附特性研究
  9. 智能客户—ERP技术新方向
  10. 10.Swoole 运行流程
  11. 宝塔linux跑tomcat,宝塔面板环境的安装(Linux、Tomcat、Node.js、Windows等环境)
  12. BizTalk Server 2010 - 使用 WCF Service [ 中篇 ]
  13. 《Java项目开发案例整合》
  14. cloudera-scm-service报错server已死,但pid文件仍存问题解决
  15. 10个必备的AutoCAD插件
  16. 戴尔服务器H330阵列卡取消磁盘阵列教程
  17. vue使用History mode之后页面无法刷新
  18. 计算机网络安全及故障谢辞,计算机网络安全初探.pdf
  19. HDRP高清渲染管线-学习资料汇总
  20. python空间点赞_用Python登录好友QQ空间点赞的示例代码

热门文章

  1. 爬取某家乐数据并部署到Linux ,实现自动爬取,定期发送邮件
  2. 【药物联合预测方向】常见专业名词及翻译
  3. Win10 + WSL2 + Ubuntu18.04 + CUDA 成功
  4. 五种常见的开源路由器第三方固件测评
  5. 布谷鸟过滤器:实际上优于布隆过滤器
  6. E: Unable to locate package winehq-stable
  7. QT + VS + C++ <Qtablewidget>
  8. flash和js通过什么类如何交互
  9. 易基因:DNA甲基化和转录组分析揭示野生草莓干旱胁迫分子调控机制|植物抗逆
  10. curl7.83.1 android 编译