
Kosaraju 算法原理
Kosaraju算法 是一种高效求解有向图强连通分量的经典算法,时间复杂度为 O(V + E),其中 V 是顶点数,E 是边数。
该算法分为两个主要步骤:
- 第一次 DFS:对原图进行深度优先搜索(DFS),记录每个节点完成遍历的顺序(即“完成时间”),并将节点按完成时间压入栈中。
- 第二次 DFS:构建原图的转置图(所有边方向反转),然后按照栈中顺序(从后往前)对转置图进行 DFS。每次 DFS 访问到的所有节点构成一个强连通分量。
C# 实现 Kosaraju 算法
下面我们用 C# 编写完整的 C#图论算法 实现。我们将使用邻接表来表示图,并借助 Stack 和 List 来辅助处理。
using System;using System.Collections.Generic;class Graph{ private int V; // 顶点数量 private List<int>[] adj; // 邻接表 public Graph(int v) { V = v; adj = new List<int>[V]; for (int i = 0; i < V; i++) adj[i] = new List<int>(); } // 添加有向边 public void AddEdge(int v, int w) { adj[v].Add(w); } // 第一次 DFS:填充完成顺序到栈中 private void FillOrder(int v, bool[] visited, Stack<int> stack) { visited[v] = true; foreach (int neighbor in adj[v]) { if (!visited[neighbor]) FillOrder(neighbor, visited, stack); } stack.Push(v); } // 转置图 public Graph GetTranspose() { Graph g = new Graph(V); for (int v = 0; v < V; v++) { foreach (int neighbor in adj[v]) { g.AddEdge(neighbor, v); // 反转边方向 } } return g; } // 第二次 DFS:打印强连通分量 private void DFSUtil(int v, bool[] visited) { visited[v] = true; Console.Write(v + " "); foreach (int neighbor in adj[v]) { if (!visited[neighbor]) DFSUtil(neighbor, visited); } } // 主函数:查找所有强连通分量 public void PrintSCCs() { Stack<int> stack = new Stack<int>(); bool[] visited = new bool[V]; // 第一步:对原图进行 DFS,填充栈 for (int i = 0; i < V; i++) { if (!visited[i]) FillOrder(i, visited, stack); } // 第二步:获取转置图 Graph gr = GetTranspose(); // 重置 visited 数组 for (int i = 0; i < V; i++) visited[i] = false; // 第三步:按栈顺序对转置图进行 DFS Console.WriteLine("强连通分量如下:"); while (stack.Count != 0) { int v = stack.Pop(); if (!visited[v]) { gr.DFSUtil(v, visited); Console.WriteLine(); // 换行表示一个 SCC 结束 } } }}// 示例使用class Program{ static void Main() { Graph g = new Graph(5); g.AddEdge(1, 0); g.AddEdge(0, 2); g.AddEdge(2, 1); g.AddEdge(0, 3); g.AddEdge(3, 4); g.PrintSCCs(); // 输出: // 0 2 1 // 3 // 4 }}
代码解析
上述代码实现了完整的 强连通分量实现 流程:
Graph 类使用邻接表存储图结构。 FillOrder 方法执行第一次 DFS,并将节点按完成顺序压入栈。 GetTranspose 方法生成原图的转置图。 PrintSCCs 是主入口,协调两次 DFS 并输出结果。
总结
通过本教程,你已经掌握了如何在 C# 中使用 Kosaraju算法 查找有向图的强连通分量。无论你是准备面试、学习图论,还是开发需要图分析功能的应用,这项技能都非常实用。
记住,理解算法背后的逻辑比死记代码更重要。建议你动手修改示例图,观察输出变化,加深理解。
希望这篇关于 C#强连通分量 的教程对你有所帮助!