0

0

c++如何实现拓扑排序算法_c++ 入度统计与AOV网活动调度【案例】

尼克

尼克

发布时间:2025-12-29 15:18:08

|

294人浏览过

|

来源于php中文网

原创

拓扑排序的核心判断条件是图中是否存在环,即遍历结束后输出顶点数是否等于总顶点数;若不等则存在环,排序失败。

c++如何实现拓扑排序算法_c++ 入度统计与aov网活动调度【案例】

拓扑排序的核心判断条件是什么

拓扑排序只适用于有向无环图(DAG)。如果图中存在环,indegree[v] == 0 的节点在某轮遍历后彻底消失,队列/变空但仍有未访问节点——此时可直接判定环存在,排序失败。

实际编码中不能只看最终是否输出了全部顶点,必须检查输出顶点数是否等于图中顶点总数。否则就是隐含环,比如输入边 0→11→22→0 时,所有节点入度始终为 1,queue 从不入队,结果为空。

用 vector> 存邻接表 + indegree 数组怎么写

这是最常用、最易调试的实现方式。邻接表用 vector>,每个 i 对应出边目标列表;入度单独开 vector indegree(n, 0),初始化时遍历所有边做 indegree[to]++

注意:顶点编号建议从 0 开始,避免下标越界;若输入是 1-based,读入后统一减 1 处理。

立即学习C++免费学习笔记(深入)”;

  • 使用 queue 实现 BFS 式拓扑序(推荐,顺序稳定)
  • 入队前务必检查 indegree[i] == 0,且入队后立即置为 -1 或用布尔数组标记已入队,防止重复入队
  • 每次从队首取节点 u,遍历其所有邻接点 v,执行 indegree[v]--;若减到 0,立刻入队
vector> graph(n);
vector indegree(n, 0);
for (auto& e : edges) {
    int u = e[0], v = e[1];
    graph[u].push_back(v);
    indegree[v]++;
}
queue q;
for (int i = 0; i < n; i++)
    if (indegree[i] == 0) q.push(i);

vector topo;
while (!q.empty()) {
    int u = q.front(); q.pop();
    topo.push_back(u);
    for (int v : graph[u]) {
        indegree[v]--;
        if (indegree[v] == 0) q.push(v);
    }
}
if (topo.size() != n) cout << "cycle detected" << endl;

为什么不能用 DFS 直接递归输出顺序

DFS 版拓扑排序不是简单地在访问时 push_back,而必须在「所有后继都访问完毕」之后才记录当前节点——即使用逆后序(post-order reverse)。否则顺序错乱,例如 A→B、A→C、B→C,DFS 若从 A 入口先走 B 再走 C,可能输出 A,B,C(错误),正确应是 A,B,C 或 A,C,B,但 C 不能在 B 前(因 B→C)。

HaiSnap
HaiSnap

一站式AI应用开发和部署工具

下载

常见错误是把 DFS 当成普通遍历,在 visit(u) 开头就加进结果,这实际得到的是某种访问序,不是拓扑序。

  • 必须用状态数组区分 unvisited / visiting / visited,遇到 visiting 就说明成环
  • 仅当递归返回前(即退出函数前)把 u 加入结果,再 reverse 整个结果
  • 多起点时需对每个未访问节点调用 DFS,不能只从 0 开始

AOV 网调度中如何处理多入度依赖与任务权重

AOV 网本身不带权,但实际调度常需扩展:比如任务耗时(权重)、资源约束、或多个前置任务必须全部完成才能开始(这正是入度统计的物理意义)。此时 indegree[u] 就是“还剩几个前置任务未完成”,只有归零才可调度。

若需计算最早开始时间(Earliest Start Time),可在拓扑序上 DP:est[v] = max(est[v], est[u] + duration[u]),前提是图按拓扑序遍历,且 u→v 是依赖边。

  • 不要在建图时合并重复边,否则 indegree 统计偏小,导致过早调度
  • 若输入含重边(如两个文件都声明依赖同一头文件),需去重或用 set 存邻接表
  • 并发调度时,同一轮中所有 indegree==0 的节点可并行执行,这时 queue 可换为 vector 批量处理

入度统计看着简单,但边界全在细节里:初始化漏节点、重边不判、环检测不校验长度、多起点遗漏——这些都会让 AOV 调度在真实项目中静默失败。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

365

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

559

2023.08.10

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

385

2023.08.14

excel制作动态图表教程
excel制作动态图表教程

本专题整合了excel制作动态图表相关教程,阅读专题下面的文章了解更多详细教程。

24

2025.12.29

freeok看剧入口合集
freeok看剧入口合集

本专题整合了freeok看剧入口网址,阅读下面的文章了解更多网址。

74

2025.12.29

俄罗斯搜索引擎Yandex最新官方入口网址
俄罗斯搜索引擎Yandex最新官方入口网址

Yandex官方入口网址是https://yandex.com;用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

207

2025.12.29

python中def的用法大全
python中def的用法大全

def关键字用于在Python中定义函数。其基本语法包括函数名、参数列表、文档字符串和返回值。使用def可以定义无参数、单参数、多参数、默认参数和可变参数的函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

16

2025.12.29

python改成中文版教程大全
python改成中文版教程大全

Python界面可通过以下方法改为中文版:修改系统语言环境:更改系统语言为“中文(简体)”。使用 IDE 修改:在 PyCharm 等 IDE 中更改语言设置为“中文”。使用 IDLE 修改:在 IDLE 中修改语言为“Chinese”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

18

2025.12.29

C++的Top K问题怎么解决
C++的Top K问题怎么解决

TopK问题可通过优先队列、partial_sort和nth_element解决:优先队列维护大小为K的堆,适合流式数据;partial_sort对前K个元素排序,适用于需有序结果且K较小的场景;nth_element基于快速选择,平均时间复杂度O(n),效率最高但不保证前K内部有序。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

12

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Rust 教程
Rust 教程

共28课时 | 3.9万人学习

Git 教程
Git 教程

共21课时 | 2.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号