图论---拓扑排序(DFS)

  1. 时间复杂度

    • 最坏情况下为O(V!),其中V是顶点数

    • 实际运行时间取决于图的拓扑结构

这个实现可以输出有向无环图的所有可能的拓扑排序,并能检测图中是否存在环。

  1. 算法思想

    • 使用回溯法枚举所有可能的拓扑排序

    • 在每一步选择当前入度为0的顶点,递归处理剩余顶点

    • 回溯时恢复入度和访问状态

  2. 关键数据结构

    • inDegree:记录每个顶点的当前入度

    • visited:标记顶点是否已被访问

    • currentOrder:存储当前正在构建的拓扑排序

    • allOrders:存储所有找到的拓扑排序

  3. 环检测

    如果无法找到任何拓扑排序(allOrders为空),说明图中存在环

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> graph;
vector<int> inDegree;
vector<bool> visited;
vector<int> currentOrder;
vector<vector<int>> allOrders;
void allTopSortUtil(int n) {
    // 标志变量,表示是否找到了一个有效的顶点
    bool flag = false;

    for (int u = 0; u < n; u++) {
        // 选择一个入度为0且未被访问的顶点
        if (inDegree[u] == 0 && !visited[u]) {
            // 减少所有邻接顶点的入度
            for (int v : graph[u]) {
                inDegree[v]--;
            }
            // 将当前顶点加入结果并标记为已访问
            currentOrder.push_back(u);
            visited[u] = true;
            // 递归处理剩余顶点
            allTopSortUtil(n);
            // 回溯:重置访问标记和入度
            visited[u] = false;
            currentOrder.pop_back();
            for (int v : graph[u]) {
                inDegree[v]++;
            }
            flag = true;
        }
    }

    // 如果没有顶点可选,说明已经得到一个完整的拓扑排序
    if (!flag) {
        if ((int)currentOrder.size() == n) {
            allOrders.push_back(currentOrder);
        }
    }
}

vector<vector<int>> allTopSorts(int n) {
    vector<int> inDegree(n, 0);
    vector<bool> visited(n, false);
    // 计算每个顶点的入度
    for (int u = 0; u < n; u++) {
        for (int v : graph[u]) {
            inDegree[v]++;
        }
    }
    allTopSortUtil(n);
    return allOrders;
}

int main() {
    // 示例:构建一个有向无环图
    int n = 6;  // 节点数量
    vector<vector<int>> graph(n);

    // 添加边
    graph[5].push_back(2);
    graph[5].push_back(0);
    graph[4].push_back(0);
    graph[4].push_back(1);
    graph[2].push_back(3);
    graph[3].push_back(1);

    // 获取所有可能的拓扑排序
    vector<vector<int>> allOrders = allTopSorts(n);

    // 输出结果
    if (allOrders.empty()) {
        cout << "图中存在环,无法进行拓扑排序!" << endl;
    } else {
        cout << "所有可能的拓扑排序:" << endl;
        for (auto& order : allOrders) {
            for (int node : order) {
                cout << node << " ";
            }
            cout << endl;
        }
        cout << "共找到 " << allOrders.size() << " 种拓扑排序" << endl;
    }

    return 0;
}
相关推荐
IronMurphy8 分钟前
【算法四十三】279. 完全平方数
算法
墨染天姬15 分钟前
【AI】Hermes的GEPA算法
人工智能·算法
papership33 分钟前
【入门级-数据结构-3、特殊树:完全二叉树的数组表示法】
数据结构·算法·链表
smj2302_7968265237 分钟前
解决leetcode第3911题.移除子数组元素后第k小偶数
数据结构·python·算法·leetcode
Beginner x_u1 小时前
链表专题:JS 实现原理与高频算法题总结
javascript·算法·链表
_深海凉_4 小时前
LeetCode热题100-寻找两个正序数组的中位数
算法·leetcode·职场和发展
旖-旎5 小时前
深搜练习(电话号码字母组合)(3)
c++·算法·力扣·深度优先遍历
谭欣辰5 小时前
C++快速幂完整实战讲解
算法·决策树·机器学习
Mr_pyx5 小时前
【LeetHOT100】随机链表的复制——Java多解法详解
算法·深度优先
AIFarmer6 小时前
【无标题】
开发语言·c++·算法