拓扑排序通俗描述及队列实现模板

题目描述:家谱树(信息学奥赛一本通-T1351)_Alex_McAvoy的博客-CSDN博客

概念部分为CSDN博主「独-」的原创文章,遵循CC 4.0 BY-SA版权协议,按要求附上原文链接:https://blog.csdn.net/qq_41713256/article/details/80805338

拓扑排序:在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。

算法概述:

  1. 先统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向的节点的入度减一。
  2. 一直做改操作,直到所有的节点都被分离出来。
  3. 如果最后不存在入度为0的节点,那就说明有环,不存在拓扑排序,也就是很多题目的无解的情况。

下面是算法的演示过程:

拓扑排序通俗描述及队列实现模板

开头所展示题目的代码实现:

#include <bits/stdc++.h>
using namespace std;

int tot, num, n, m;
// a[i][j]存点i的第j个后继点,c[i]存点i的出度,r[i]存点i的入度
int a[101][101], c[101], r[101];

// stack<int> s;
queue<int> s;

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        int j;
        cin >> j;
        while (j != 0) {
            // 数据初始化,看一下每个数组的作用应该能懂
            c[i]++;
            a[i][c[i]] = j;
            r[j]++;
            cin >> j;
        }
    }

    for (int i = 1; i <= n; i++)
        if (r[i] == 0) s.push(i);  // 最开始就是入度为0的先入队

    while (num < n) {
        int temp = s.front();  // 队头元素开始处理
        cout << temp << " ";
        s.pop();
        num++;  // 统计已经完成排序的节点
        for (int i = 1; i <= c[temp]; i++) {
            // 从图中删除当前节点,所以该节点所有后继节点的入度-1
            r[a[temp][i]]--;
            // 如果减去后入度为0,则也入队
            if (r[a[temp][i]] == 0) s.push(a[temp][i]);
        }
    }

    return 0;
}
上一篇:每日总结22


下一篇:1. 算法之 动态规划