图论---拓扑排序(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;
}
相关推荐
luckys.one1 小时前
第9篇:Freqtrade量化交易之config.json 基础入门与初始化
javascript·数据库·python·mysql·算法·json·区块链
~|Bernard|2 小时前
在 PyCharm 里怎么“点鼠标”完成指令同样的运行操作
算法·conda
战术摸鱼大师2 小时前
电机控制(四)-级联PID控制器与参数整定(MATLAB&Simulink)
算法·matlab·运动控制·电机控制
Christo32 小时前
TFS-2018《On the convergence of the sparse possibilistic c-means algorithm》
人工智能·算法·机器学习·数据挖掘
好家伙VCC3 小时前
数学建模模型 全网最全 数学建模常见算法汇总 含代码分析讲解
大数据·嵌入式硬件·算法·数学建模
liulilittle5 小时前
IP校验和算法:从网络协议到SIMD深度优化
网络·c++·网络协议·tcp/ip·算法·ip·通信
bkspiderx6 小时前
C++经典的数据结构与算法之经典算法思想:贪心算法(Greedy)
数据结构·c++·算法·贪心算法
中华小当家呐8 小时前
算法之常见八大排序
数据结构·算法·排序算法
沐怡旸8 小时前
【算法--链表】114.二叉树展开为链表--通俗讲解
算法·面试
一只懒洋洋9 小时前
K-meas 聚类、KNN算法、决策树、随机森林
算法·决策树·聚类