当前位置: 首页 > news >正文

44.Acwing基础课第848题-简单-有向图的拓扑序列

44.Acwing基础课第848题-简单-有向图的拓扑序列

题目描述

给定一个 n个点 m条边的有向图,点的编号是 1到 n,图中可能存在重边和自环。

请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。

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

输入格式

第一行包含两个整数 n和 m。

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

输出格式

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

数据范围

1≤n,m≤105

输入样例:

3 3
1 2
2 3
1 3

输出样例:

1 2 3

绘图14

解题思路

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

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;const int N = 100010;int n,m;
int h[N],e[N],ne[N],idx;
int q[N],d[N];//q[]表示队列,d表示入度//构建节点a到b的边
void add(int a, int b)
{e[idx] = b;ne[idx] = h[a];h[a] = idx;idx++;
}bool topsort()
{int hh = 0, tt = -1;for(int i = 1; i <= n; i++)//所有入度为0的点入队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];d[j]--;if(d[j] == 0) q[++tt] = j;}}return tt == n-1;
}int main()
{cin >> n >> m;memset(h, -1, sizeof h);for(int i = 1; i <= m; i++){int x, y;cin >> x >> y;add(x,y);d[y]++;}if(topsort()){for(int i = 0; i < n; i++) printf("%d ",q[i]);puts("");}else puts("-1");return 0;
}

这段代码的核心功能是,通过拓扑排序算法来确定一个有向图中的顶点顺序,这个顺序满足:对于图中的每一对顶点uv,如果存在从uv的路径,则在排序结果中u出现在v之前。这是有向无环图(DAG)的一种特性。

  1. 邻接表的构建
    • add函数用于在邻接表中添加一条从顶点a到顶点b的边。它的工作原理是将新边插入到以a为头的链表的起始位置。
    • h[a]记录首个离开a的边的索引,e[idx]是该边到达的顶点,ne[idx]记录该边的下一条边的索引。idx是全局计数器,用于分配新边的索引。
  2. 拓扑排序算法
    • topsort函数实现拓扑排序。它使用队列q[N]来记录排序结果。
    • 先将所有入度为0的顶点添加到队列中,这些顶点没有任何入边,并且它们将是拓扑排序的起始顶点。
    • 然后,算法进入循环,每次从队列中取出一个顶点t,并检查每一个t的后继者j。每处理一个后继者,就将该顶点的入度d[j]减1,因为我们已经“考虑”了从 tj的边。
    • 如果后继者j的入度经过减少后变为0,则它也没有未处理的入边了,可以放入队列,等待后续处理。
    • 排序成功的标志是所有顶点都被处理过一次,即队列包含了所有n个顶点。
  3. 主函数
    • main函数从标准输入读入顶点数n和边数m,初始化邻接表h[],并循环读取每一条边,更新邻接表和顶点入度d[]
    • 调用topsort函数执行拓扑排序。如果排序成功,输出排好序的顶点序列;否则,输出-1表示该图不是DAG,不能进行拓扑排序。
  4. 关于d[j]--
    • 对于d[j]--,这并不会导致入度为负数值。当我们从队列中取出顶点t时,t的入度肯定是0, 因为只有入度为0的点才会被加入队列。然后,我们遍历t的所有出边。在这个过程中,我们减少每个后继者j的入度,这表示我们去掉了从tj的一条边。所以,d[j]--实际上是一个计数的减少过程,由于边的移除而减少。所以,d[j]最多只会从1减到0,而不会减到负数。

拓扑排序的最终结果将是所有顶点的一个线性排序,满足有向无环图中的先后依赖关系。如果图中存在环,由于终将遇到没有入度会变为0的顶点(因为环里总有边指向环内的顶点),那么不会所有的顶点都能进入队列,因此拓扑排序失败。

http://www.jsqmd.com/news/607891/

相关文章:

  • 智能问数:表级索引 vs 表+字段二级索引方案对比总结
  • DS18B20寄生供电模式全解析:3.3V系统下的STM32省电测温方案
  • 兰州发电机组哪家强?6大本土品牌优势对比与选型指南 - 深度智识库
  • 一、先明确你的场景 你是本地已经有 GIS.Api 项目代码,要推送到这个新建的空仓库,对应页面里的「从命令行推送已经创建的仓库」模块。
  • 2026年4月实测,宁波本地top5装修设计公司排名(精装改造与高还原篇) - 疯一样的风
  • STM32F103C8T6 Bootloader跳转APP就死机?一个关闭中断的指令救了我
  • 2026 年软件开发五大品牌排名及解析软件开发五大品牌 - 十大品牌榜
  • tp3.2开启Redis后S()函数格式化字符串数据,一个小坑
  • 火锅底料批发源头厂家合作案例多的有哪些,价格怎样? - 工业推荐榜
  • 2026年甘肃私立学校甄选 覆盖全学段与各类家庭需求 资质齐全教学优质 - 深度智识库
  • stanford_dl_ex代码结构深度解析:从数据加载到模型评估的完整流程
  • 2026年支座灌浆料厂家推荐:支座灌浆料/无收缩灌浆料/高强灌浆料/通用灌浆料/设备基础灌浆料专业供应商选型指南 - 品牌推荐官
  • 智能家居选哪种无线协议?Zigbee、WiFi、蓝牙优缺点全解析(附场景推荐)
  • 2025年度排行,宁波高口碑与综合实力top5装修设计公司排名 - 疯一样的风
  • 天虹购物卡回收,现金秒到账! - 团团收购物卡回收
  • 2026年重庆成都四川火锅底料批发代理商专业排名,哪家更值得选 - 工业品牌热点
  • 2026 年分销系统五大品牌排名及解析 - 十大品牌榜
  • 2026泵阀、仪器仪表入驻平台对比:性价比与效果双优选择 - 品牌推荐大师
  • Unity路径有中文就报错?手把手教你解决Autoware高精地图插件导入的坑
  • 2026万里通积分卡回收技巧分享,让优惠尽在掌握! - 团团收购物卡回收
  • #2026年最新家具面料厂家评测!广东佛山源头工厂榜单发布,赋能高端软装升级 - 十大品牌榜
  • 什么眼霜长期抗老最好?2026年十款维稳眼霜排行榜,解析长期抗老保养选什么眼霜最好 - 博客万
  • 嵌入式云设备时间格式化库:轻量、确定性、RFC 3339 兼容
  • 2026年四川清汤串串底料费用揭秘,琢翔食品性价比如何 - mypinpai
  • 一文读懂10英寸平板尺寸:从屏幕比例到实际机身尺寸
  • 不用海康SDK,用Python+ISAPI搞定热成像数据,我踩过的坑都在这了
  • 2026年护发精油推荐榜单:6款明星产品大盘点 - 博客万
  • 聊聊服务不错的玉米制糁设备工厂,河南粮院机械靠谱之选 - myqiye
  • 2026年滋补品加工AI搜索优化服务商选型分析与主流机构能力梳理 - 小白条111
  • 2026 年有赞商城五大品牌排名及解析 - 十大品牌榜