拓扑排序基础
什么是拓扑排序
对有向无环图(DAG)的顶点排序,保证每条边的起点都排在终点前面。
例如 1 -> 2 在这里1是起点,2是终点。
如何实现
输入比较烦,但归根结底还是建DAG,看看注释:
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 110;
vector<int> a[N];
int r[N];
signed main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
while (true) { // 只是输入猎奇
int c;
cin >> c;
if (!c) break;
a[i].push_back(c);
r[c]++; // 统计一个节点的入度
}
}
queue<int> q;
for (int i = 1; i <= n; i++) {
if (!r[i]) {
q.push(i); // 一开始有哪些入度为0的点,即老祖宗,有时不止一个(不是此题)
}
}
while (!q.empty()) { // 是不是有点像bfs
int now = q.front();
cout << now << " "; // 输出拓扑序,拓扑序不是唯一的
q.pop();
for (int i : a[now]) {
r[i]--; // 入度 - 1
if (!r[i]) q.push(i); // 有没有新的入度为0的,即辈分最大的的人
}
}
return 0;
}
有什么用
本人才疏学浅,目前只知道两个常用的。
判断是否有环
废话:不一定是DAG
如果不是每个点都入过队列,但是结束了,说明有一个回合没有一个入度为0的点了,环就是这样
最长(短)路
在有向无环图(DAG)中,先跑出拓扑序,再按序对每条边做松弛:
- 最短路:
dist[v] = min(dist[v], dist[u]+w) - 最长路:
dist[v] = max(dist[v], dist[u]+w)
DAG还是别用Dij了吧...
Why?
因为拓扑序保证了:处理 u 时,起点到 u 的所有路径都已经算完了,不会再有后面的点回头更新 u,所以直接松弛 v 就一定是最优的。
谢谢观看!

浙公网安备 33010602011771号