图论---拓扑排序(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;
}
相关推荐
阿pin18 分钟前
Java随笔-红黑树
java·python·算法·红黑树
Hi李耶19 分钟前
【LeetCode】17.电话号码的字母组合
算法·leetcode·职场和发展
江畔柳前堤9 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore10 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考12 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX12 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面13 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号13 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽13 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI13 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研