拓扑排序基础

什么是拓扑排序

有向无环图(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 就一定是最优的。


谢谢观看!

posted @ 2026-04-06 22:40  PCMSFV  阅读(4)  评论(0)    收藏  举报