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

拓扑排序(竞赛)

一、介绍

1、介绍

有时候做一些事情是有前置条件的,能正确把这些事情排序出来的算法就是拓扑排序。

拓扑排序解决的是有向无环图,但是可以也可以判环。

2、实现思路

步骤1:一开始入度为0的节点是没有前置条件的,全部入队。

步骤2:出队头,删边,有节点入度为0,入队。

步骤3:一直循环步骤2,直到队列为空,即没有节点入度为0。

此时两种情况:

(1)全部节点入队出队过,说明全部任务做完,符合要求.

(2)没有全部节点入队出队过,说明有环。

3、例题

B3644 【模板】拓扑排序 / 家谱树 - 洛谷

#include <bits/stdc++.h>
using namespace std;int n;
vector<int> rel[110];
int in[110];
int cnt = 0;// 拓扑排序:一开始把入度为0的节点加入队列,开始循环,每次队头出一个节点,删除关联边(对应终点入度--,如果减到0就入队),直到全部节点入队或没有入度为0的节点终止
// 如果终止后不是所有节点都入过队那就说明有环,即cnt != nint main()
{cin >> n;for(int i = 1; i <= n; i++){int x;while(cin >> x, x){rel[i].push_back(x);in[x]++;}}queue<int> q;for(int i = 1; i <= n; i++)if(in[i] == 0)q.push(i);cnt = q.size();while(q.size()){int x = q.front();cout << x << ' ';q.pop();for(auto num : rel[x]){in[num]--;if(in[num] == 0){q.push(num);cnt++;}}}return 0;
}

二、例题

拓扑排序重点是排出一个合法的顺序,所以题型多样,可以和动态规划相结合,可以看成普通动态规划是按从小到大或从大到小顺序更新 dp 表,而与拓扑排序结合后用的是拓扑排序的顺序更新 dp 表,初始化一般在步骤一完成。

1、摄像头

P2712 摄像头 - 洛谷

#include <bits/stdc++.h>
using namespace std;int n;
vector<int> rel[510];
int in[510];
int cnt = 0;
vector<int> she;int main()
{cin >> n;for(int i = 1; i <= n; i++){int x;cin >> x;she.push_back(x);int j;cin >> j;while(j--){cin >> x;in[x]++;}}queue<int> q;for(auto x : she)if(in[x] == 0)q.push(x);cnt = q.size();while(q.size()){int x = q.front();q.pop();for(auto num : rel[x]){in[num]--;if(in[num] == 0){q.push(num);cnt++;}}}if(cnt == n)cout << "YES";else cout << n - cnt;return 0;
}

2、最大食物链计数

P4017 最大食物链计数 - 洛谷

#include <bits/stdc++.h>
using namespace std;const int mod = 80112002;
int dp[5010];
vector<int> rel[5010]; // 被吃
int in[5010]; // 吃节点的入度
int n, m;
int ans = 0;
// dp[i]表示从最前面到i生物的全部路径数
int main()
{cin >> n >> m;while(m--){int x, y;cin >> x >> y;rel[y].push_back(x);in[x]++;}queue<int> q;for(int i = 1; i <= n; i++){if(in[i] == 0){q.push(i);dp[i] = 1;}}while(q.size()){int x = q.front();q.pop();for(auto num : rel[x]){in[num]--;if(in[num] == 0)q.push(num);dp[num] = (dp[num] + dp[x]) % mod;}}for(int i = 1; i <= n; i++){if(rel[i].size() == 0){ans = (ans + dp[i]) % mod;}}cout << ans;return 0;
}

3、杂务

P1113 杂务 - 洛谷

#include <bits/stdc++.h>
using namespace std;int n;
vector<int> rel[10010];
int t[10010];
int in[10010];
int dp[10010];// 由于每一层的任务不是同时开始的,所以前置任务的最早完成时间是当前任务的开始时间
// 动态规划+拓扑排序
// dp[i]表示i任务最早完成时间
// dp[i] = max(dp前置任务) + t[i];int main()
{cin >> n;for(int i = 1; i <= n; i++){int x;cin >> x;cin >> t[x];int j;while(cin >> j, j){rel[j].push_back(x);in[x]++;}}queue<int> q;int ans = 0;for(int i = 1; i <= n; i++){if(in[i] == 0){q.push(i);dp[i] = t[i];}}while(q.size()){int x = q.front();ans = max(ans, dp[x]);q.pop();for(auto num : rel[x]){in[num]--;dp[num] = max(dp[num], dp[x] + t[num]);ans = max(ans, dp[num]);if(in[num] == 0)q.push(num);}}cout << ans;return 0;
}
http://www.xdnf.cn/news/428149.html

相关文章:

  • 按键精灵ios脚本新增元素功能助力辅助工具开发(二)
  • 春秋云镜 Time Writeup
  • 面试中被问到谈谈你对threadlocal的理解
  • 2025年5月-信息系统项目管理师高级-软考高项一般计算题
  • 基于Session实现短信登录全流程详解
  • 数据治理的核心
  • 论文知识总结
  • 日常知识点之随手问题整理(vcpkg安装osgearth并进行测试简单整理)
  • 【Ubuntu】扩充磁盘大小
  • 求1+3+5+7+9+…,其和小于等于500 的最大项
  • Java线程池性能优化全解析:从配置到实践
  • Redis学习笔记
  • SAP Business One(B1)打开自定义对象报错【Failed to initialize document numbering:】
  • 大模型核心运行机制
  • 玩转ChatGPT:DeepSeek实战(统一所在地格式)
  • 基于STM32、HAL库的TDA7719TR音频接口芯片驱动程序设计
  • RK3568移植鸿蒙系统openharmony-5.1.0-release
  • 【愚公系列】《Manus极简入门》036-物联网系统架构师:“万物互联师”
  • 数据结构基础--蓝桥杯备考
  • 在Flutter上如何实现按钮的拖拽效果
  • Ceph 集群常用管理命令
  • esp32硬件支持AT指令
  • 什么类型的网站适合用WAF?Web应用防火墙的适用场景解析
  • Python(1) 做一个随机数的游戏
  • MySQL索引底层数据结构与算法
  • Vue 2 和 Vue 3的比较(二、语法差异)
  • Excel的详细使用指南
  • Mac修改hosts文件方法
  • Linux文件编程——标准库函数fopen、fread、fwrite等函数
  • Confusion2(Python反序列化+JWT)