/// <summary> /// Wyznacza silnie spójne składowe /// </summary> /// <param name="g">Badany graf</param> /// <param name="scc">Silnie spójne składowe (parametr wyjściowy)</param> /// <returns>Liczba silnie spójnych składowych</returns> /// <remarks> /// scc[v] = numer silnie spójnej składowej do której należy wierzchołek v<br/> /// (numerujemy od 0)<br/> /// <br/> /// Metoda uruchomiona dla grafu nieskierowanego zgłasza wyjątek <see cref="System.ArgumentException"/>. /// <br/> /// Graf wejściowy pozostaje niezmieniony. /// </remarks> public static int StronglyConnectedComponents(this Graph g, out int[] scc) { if (!g.Directed) { throw new System.ArgumentException("Graf jest nieskierowany"); } // Algorytm Kosaraju int[] initialOrder = new int[g.VerticesCount]; int currentOrderValue = 0; g.GeneralSearchAll <EdgesStack>(null, v => { initialOrder[currentOrderValue++] = v; return(true); }, null, out int cc); int[] vertexInComponent = new int[g.VerticesCount]; Graph reversed = g.CustomReverse(); // można skorzystać z bibliotecznego g.Reverse, ale zapewne o to chodziło w zadaniu, żeby zrobić własne bool[] visited = new bool[g.VerticesCount]; int leftToVisit = g.VerticesCount; int currentComponent = 0; while (leftToVisit > 0) { int startingVertex = 0; for (int i = g.VerticesCount - 1; i >= 0; i--) { int v = initialOrder[i]; if (!visited[v]) { startingVertex = v; break; } } reversed.GeneralSearchFrom <EdgesStack>(startingVertex, v => { leftToVisit--; vertexInComponent[v] = currentComponent; return(true); }, null, null, visited); currentComponent++; } scc = vertexInComponent; return(currentComponent); }