图论---拓扑排序(DFS)
-
时间复杂度:
-
最坏情况下为O(V!),其中V是顶点数
-
实际运行时间取决于图的拓扑结构
-
这个实现可以输出有向无环图的所有可能的拓扑排序,并能检测图中是否存在环。
-
算法思想:
-
使用回溯法枚举所有可能的拓扑排序
-
在每一步选择当前入度为0的顶点,递归处理剩余顶点
-
回溯时恢复入度和访问状态
-
-
关键数据结构:
-
inDegree
:记录每个顶点的当前入度 -
visited
:标记顶点是否已被访问 -
currentOrder
:存储当前正在构建的拓扑排序 -
allOrders
:存储所有找到的拓扑排序
-
-
环检测:
如果无法找到任何拓扑排序(allOrders
为空),说明图中存在环
#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;
}