コード例 #1
0
        /// <summary>
        /// <para>
        /// This implementation produces results augmented with information on SCCs within the graph.
        /// </para>
        /// <para>
        /// To prevent traversal of an edge, the <see cref="IEdgeWeigher{V, E}"/> should
        /// return a negative value as an edge weigher.
        /// </para>
        /// </summary>
        /// <param name="graph">The graph to search.</param>
        /// <param name="weigher">The weigher to use.</param>
        /// <returns>The SCC search result.</returns>
        public IResultBase <V, E> Search(IGraph <V, E> graph, IEdgeWeigher <V, E> weigher)
        {
            SccResult result = new SccResult(graph);

            foreach (V vertex in graph.Vertices)
            {
                VertexData data = result.GetData(vertex);
                if (data is null)
                {
                    Connect(graph, vertex, weigher, result);
                }
            }
            return(result.Build());
        }
コード例 #2
0
        /// <summary>
        /// Scans the specified graph, using recursion, and produces SCC results.
        /// </summary>
        /// <param name="graph">The graph to search.</param>
        /// <param name="vertex">The current vertex to scan and connect.</param>
        /// <param name="weigher">The optional weigher to use.</param>
        /// <param name="result">The graph search result.</param>
        /// <returns>Augmentation vertex data for the current vertex.</returns>
        private VertexData Connect(IGraph <V, E> graph, V vertex, IEdgeWeigher <V, E> weigher, SccResult result)
        {
            VertexData data = result.AddData(vertex);

            // Scan through all egress edges of the current vertex.
            foreach (E edge in graph.GetEdgesFrom(vertex))
            {
                V nextVertex = edge.Dst;

                // If edge is not viable, skip it.
                if (weigher != null && !weigher.GetWeight(edge).IsViable)
                {
                    continue;
                }

                // Attempt to get the augmentation vertex data for the next vertex.
                VertexData nextData = result.GetData(nextVertex);
                if (nextData is null)
                {
                    // Next vertex has not been visited yet, so do this now.
                    nextData     = Connect(graph, nextVertex, weigher, result);
                    data.LowLink = Math.Min(data.LowLink, nextData.LowLink);
                }
                else if (result.Visited(nextData))
                {
                    // Next vertex has been visited, which means
                    // it is in the same cluster as the current vertex.
                    data.LowLink = Math.Min(data.LowLink, nextData.Index);
                }
            }

            if (data.LowLink == data.Index)
            {
                result.AddCluster(data);
            }
            return(data);
        }