图论---拓扑排序(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;
}
相关推荐
LYFlied12 分钟前
【每日算法】LeetCode 105. 从前序与中序遍历序列构造二叉树
数据结构·算法·leetcode·面试·职场和发展
DanyHope18 分钟前
LeetCode 206. 反转链表:迭代 + 递归双解法全解析
算法·leetcode·链表·递归·迭代
NAGNIP21 分钟前
才发现TensorBoard是个可视化的神器!
算法
_dindong27 分钟前
算法杂谈:回溯路线
数据结构·算法·动态规划·bfs·宽度优先
咋吃都不胖lyh28 分钟前
详解 UCB 算法的置信区间与核心逻辑(通俗 + 公式 + 实例)
人工智能·算法·机器学习
DanyHope36 分钟前
LeetCode 两数之和:从 O (n²) 到 O (n),空间换时间的经典实践
前端·javascript·算法·leetcode·职场和发展
free-elcmacom42 分钟前
机器学习高阶教程<6>推荐系统高阶修炼手册:混排、多任务与在线学习,解锁精准推荐新境界
人工智能·python·学习·算法·机器学习·机器人
断剑zou天涯43 分钟前
【算法笔记】AC自动机
java·笔记·算法
IT猿手1 小时前
基于粒子群算法与动态窗口混合的无人机三维动态避障路径规划研究,MATLAB代码
算法·matlab·无人机·多目标优化算法·多目标算法
民乐团扒谱机1 小时前
【微实验】仿AU音频编辑器开发实践:从零构建音频可视化工具
算法·c#·仿真·audio·fft·频谱