EVERYTHING HAPPENS FOR THE |

wnsyou

园龄:2年4个月粉丝:19关注:16

2023-10-07 21:39阅读: 69评论: 0推荐: 0

拓扑排序和拓扑序

OI-wiki Link

众所周知,拓扑序可以决定 dp 的顺序,而拓扑排序则是用于求图上的点的拓扑序。

对于图上任意两点 x,y(xy),当 x 的拓扑序大于 y 的拓扑序时,x 不能到达 y。所以在有向有环图和无向图上是不存在拓扑序的。

而拓扑排序则是用于求 DAG(有向无环图)的拓扑序。

思想

从小到大分配拓扑序。

对于一个节点 x,如果它的入度为 0,那么就代表在原图上所有可以到达 x 的点的拓扑序都小于 x 的拓扑序,那么就删除节点 x,继续进行下一次分配。

实现

用一个队列来维护入度为 0 的节点。

首先把所有原图中的入度为 0 压入队列,然后每次取出队头元素 x,删除它。

删除就是将所有 x 连向的节点的入度减 1,如果其中有一个节点的入度变为 0 了,将其压入队列即可。

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

虽然这题 n 范围很小,但是就把它当 105 这种级别来做。

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int n, x, b[110];
vector<int> g[110];
queue<int> q;
int main () {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
while (cin >> x && x) {
g[i].push_back(x), b[x]++;
}
}
for (int i = 1; i <= n; i++) {
if (!b[i]) {
q.push(i);
}
}
for (int i = 1; i <= n; i++) {
x = q.front();
q.pop();
cout << x << ' ';
for (int j : g[x]) {
b[j]--;
if (!b[j]) {
q.push(j);
}
}
}
return 0;
}

n 为节点数,m 为边数,所有复杂度为 O(n+m)

一些应用

  • 拓扑序决定了 dp 的顺序,因此当要做图上 dp 时可以直接边拓扑排序边 dp。
  • 给定一个有向图,可以通过拓扑排序来判环,当拓扑排序后仍有节点没有被规定拓扑序时就是有环。

本文作者:wnsyou の blog

本文链接:https://www.cnblogs.com/wnsyou-blog/p/topo_sort.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wnsyou  阅读(69)  评论(0编辑  收藏  举报
  1. 1 勝利への道 安藤浩和
  2. 2 Minecraft’s End Eric Fullerton
  3. 3 月光曲完整版 贝多芬 云熙音乐
  4. 4 平凡之路 (Live版) 朴树
  5. 5 Minecraft C418
  6. 6 Paradise NiziU
  7. 7 叫我,灰原哀 龙大人不喷火
  8. 8 心机之蛙,一直摸你肚子 ——《名侦探柯南》原创同人曲 炊饭,叶辞樱,温海,寒砧,南柯柯,小茜玛姬,盛姝,阿崔Ac,贝壳初,千湛,兮茶子DaYu,乔慕,黎鹿北,起千温卿,遮阳伞,曲悠
  9. 9 战 歌 此去经年
月光曲完整版 贝多芬 - 云熙音乐
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

暂无歌词

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示