示例#1
0
        /// <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);
        }