Exemplo n.º 1
0
            private IEnumerable <IDiGraph <T, TWeight> > StrongConnect(T vertex)
            {
                var metadata = _metadataLookup[vertex];

                metadata.Index   = _index;
                metadata.LowLink = _index;
                _index          += 1;
                _stack.Push(vertex);
                metadata.OnStack = true;

                foreach (var outEdge in _graph.GetOutgoingEdges(vertex))
                {
                    var targetVertex = outEdge.TargetVertex;

                    var outMetadata = _metadataLookup[targetVertex];
                    if (outMetadata.Index == -1)
                    {
                        foreach (var result in StrongConnect(targetVertex))
                        {
                            yield return(result);
                        }
                    }
                    if (outMetadata.OnStack)
                    {
                        metadata.LowLink = Math.Min(metadata.LowLink, outMetadata.LowLink);
                    }
                }

                if (metadata.LowLink != metadata.Index)
                {
                    yield break;
                }

                IDiGraph <T, TWeight> componentGraph = new DiGraph <T, TWeight>(_graph.DefaultEdgeWeight);

                T wVertex;

                do
                {
                    wVertex = _stack.Pop();
                    var stackNodeMetadata = _metadataLookup[wVertex];
                    stackNodeMetadata.OnStack = false;
                    componentGraph.AddVertex(wVertex);
                } while (!EqualityComparer <T> .Default.Equals(vertex, wVertex));

                var filteredEdges = componentGraph.Vertices
                                    .SelectMany(v => _graph.GetOutgoingEdges(v))
                                    .Where(e => componentGraph.Vertices.Contains(e.SourceVertex))
                                    .Where(e => componentGraph.Vertices.Contains(e.TargetVertex));

                foreach (var edge in filteredEdges)
                {
                    componentGraph.AddEdge(edge.SourceVertex, edge.TargetVertex, edge.Weight);
                }

                yield return(componentGraph);
            }