protected static void TryGetEdges_ImmutableGraph_Test( IMutableVertexAndEdgeSet <int, Edge <int> > wrappedGraph, Func <IIncidenceGraph <int, Edge <int> > > createGraph) { var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 2); var edge3 = new Edge <int>(1, 3); var edge4 = new Edge <int>(2, 2); var edge5 = new Edge <int>(2, 4); var edge6 = new Edge <int>(3, 1); wrappedGraph.AddVerticesAndEdgeRange(new[] { edge1, edge2, edge3, edge4, edge5, edge6 }); IIncidenceGraph <int, Edge <int> > graph = createGraph(); Assert.IsFalse(graph.TryGetEdges(0, 10, out _)); Assert.IsFalse(graph.TryGetEdges(0, 1, out _)); Assert.IsTrue(graph.TryGetEdges(2, 2, out IEnumerable <Edge <int> > gotEdges)); CollectionAssert.AreEqual(new[] { edge4 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(2, 4, out gotEdges)); CollectionAssert.AreEqual(new[] { edge5 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(1, 2, out gotEdges)); CollectionAssert.AreEqual(new[] { edge1, edge2 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(2, 1, out gotEdges)); CollectionAssert.IsEmpty(gotEdges); }
protected static void TryGetEdge_ImmutableGraph_ReversedTest( IMutableVertexAndEdgeSet <int, Edge <int> > wrappedGraph, Func <IIncidenceGraph <int, SReversedEdge <int, Edge <int> > > > createGraph) { var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 2); var edge3 = new Edge <int>(1, 3); var edge4 = new Edge <int>(2, 2); var edge5 = new Edge <int>(2, 4); var edge6 = new Edge <int>(3, 1); wrappedGraph.AddVerticesAndEdgeRange(new[] { edge1, edge2, edge3, edge4, edge5, edge6 }); IIncidenceGraph <int, SReversedEdge <int, Edge <int> > > graph = createGraph(); Assert.IsFalse(graph.TryGetEdge(0, 10, out _)); Assert.IsFalse(graph.TryGetEdge(0, 1, out _)); Assert.IsTrue(graph.TryGetEdge(4, 2, out SReversedEdge <int, Edge <int> > gotEdge)); AssertSameReversedEdge(edge5, gotEdge); Assert.IsTrue(graph.TryGetEdge(2, 2, out gotEdge)); AssertSameReversedEdge(edge4, gotEdge); Assert.IsTrue(graph.TryGetEdge(2, 1, out gotEdge)); AssertSameReversedEdge(edge1, gotEdge); Assert.IsFalse(graph.TryGetEdge(1, 2, out _)); }
/// <summary> /// Construct a filtered graph with an edge and a vertex predicate. /// </summary> /// <param name="g">graph to filter</param> /// <param name="edgePredicate">edge predicate</param> /// <param name="vertexPredicate">vertex predicate</param> /// <exception cref="ArgumentNullException"> /// g, edgePredicate or vertexPredicate are null /// </exception> public FilteredIncidenceGraph( IIncidenceGraph g, IEdgePredicate edgePredicate, IVertexPredicate vertexPredicate) : base(g,edgePredicate,vertexPredicate) { }
protected static void ContainsEdge_SourceTarget_ImmutableGraph_ReversedTest( [NotNull] IMutableVertexAndEdgeSet <int, Edge <int> > wrappedGraph, [NotNull, InstantHandle] Func <IIncidenceGraph <int, SReversedEdge <int, Edge <int> > > > createGraph) { IIncidenceGraph <int, SReversedEdge <int, Edge <int> > > graph = createGraph(); var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 3); var edge3 = new Edge <int>(2, 2); Assert.IsFalse(graph.ContainsEdge(1, 2)); Assert.IsFalse(graph.ContainsEdge(2, 1)); wrappedGraph.AddVerticesAndEdge(edge1); graph = createGraph(); Assert.IsFalse(graph.ContainsEdge(1, 2)); Assert.IsTrue(graph.ContainsEdge(2, 1)); wrappedGraph.AddVerticesAndEdge(edge2); graph = createGraph(); Assert.IsFalse(graph.ContainsEdge(1, 3)); Assert.IsTrue(graph.ContainsEdge(3, 1)); wrappedGraph.AddVerticesAndEdge(edge3); graph = createGraph(); Assert.IsTrue(graph.ContainsEdge(2, 2)); // Vertices is not present in the graph Assert.IsFalse(graph.ContainsEdge(0, 4)); Assert.IsFalse(graph.ContainsEdge(1, 4)); Assert.IsFalse(graph.ContainsEdge(4, 1)); }
protected static void TryGetEdges_ImmutableGraph_ReversedTest( [NotNull] IMutableVertexAndEdgeSet <int, Edge <int> > wrappedGraph, [NotNull, InstantHandle] Func <IIncidenceGraph <int, SReversedEdge <int, Edge <int> > > > createGraph) { var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 2); var edge3 = new Edge <int>(1, 3); var edge4 = new Edge <int>(2, 2); var edge5 = new Edge <int>(2, 4); var edge6 = new Edge <int>(3, 1); wrappedGraph.AddVerticesAndEdgeRange(new[] { edge1, edge2, edge3, edge4, edge5, edge6 }); IIncidenceGraph <int, SReversedEdge <int, Edge <int> > > graph = createGraph(); Assert.IsFalse(graph.TryGetEdges(0, 10, out _)); Assert.IsFalse(graph.TryGetEdges(0, 1, out _)); Assert.IsTrue(graph.TryGetEdges(2, 2, out IEnumerable <SReversedEdge <int, Edge <int> > > gotEdges)); AssertSameReversedEdges(new[] { edge4 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(4, 2, out gotEdges)); AssertSameReversedEdges(new[] { edge5 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(2, 1, out gotEdges)); AssertSameReversedEdges(new[] { edge1, edge2 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(1, 2, out gotEdges)); CollectionAssert.IsEmpty(gotEdges); }
protected static void ContainsEdge_SourceTarget_ImmutableGraph_Test <TEdge>( IMutableVertexAndEdgeSet <int, Edge <int> > wrappedGraph, Func <IIncidenceGraph <int, TEdge> > createGraph) where TEdge : IEdge <int> { IIncidenceGraph <int, TEdge> graph = createGraph(); var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 3); var edge3 = new Edge <int>(2, 2); Assert.IsFalse(graph.ContainsEdge(1, 2)); Assert.IsFalse(graph.ContainsEdge(2, 1)); wrappedGraph.AddVerticesAndEdge(edge1); graph = createGraph(); Assert.IsTrue(graph.ContainsEdge(1, 2)); Assert.IsFalse(graph.ContainsEdge(2, 1)); wrappedGraph.AddVerticesAndEdge(edge2); graph = createGraph(); Assert.IsTrue(graph.ContainsEdge(1, 3)); Assert.IsFalse(graph.ContainsEdge(3, 1)); wrappedGraph.AddVerticesAndEdge(edge3); graph = createGraph(); Assert.IsTrue(graph.ContainsEdge(2, 2)); // Vertices is not present in the graph Assert.IsFalse(graph.ContainsEdge(0, 4)); Assert.IsFalse(graph.ContainsEdge(1, 4)); Assert.IsFalse(graph.ContainsEdge(4, 1)); }
protected static void TryGetEdges_Test( [NotNull] IIncidenceGraph <int, Edge <int> > graph, [NotNull, InstantHandle] Action <IEnumerable <Edge <int> > > addVerticesAndEdgeRange) { var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 2); var edge3 = new Edge <int>(1, 3); var edge4 = new Edge <int>(2, 2); var edge5 = new Edge <int>(2, 4); var edge6 = new Edge <int>(3, 1); addVerticesAndEdgeRange(new[] { edge1, edge2, edge3, edge4, edge5, edge6 }); Assert.IsFalse(graph.TryGetEdges(0, 10, out _)); Assert.IsFalse(graph.TryGetEdges(0, 1, out _)); Assert.IsTrue(graph.TryGetEdges(2, 2, out IEnumerable <Edge <int> > gotEdges)); CollectionAssert.AreEqual(new[] { edge4 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(2, 4, out gotEdges)); CollectionAssert.AreEqual(new[] { edge5 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(1, 2, out gotEdges)); CollectionAssert.AreEqual(new[] { edge1, edge2 }, gotEdges); Assert.IsTrue(graph.TryGetEdges(2, 1, out gotEdges)); CollectionAssert.IsEmpty(gotEdges); }
/// <summary> /// Construct a filtered graph with an edge and a vertex predicate. /// </summary> /// <param name="g">graph to filter</param> /// <param name="edgePredicate">edge predicate</param> /// <param name="vertexPredicate">vertex predicate</param> /// <exception cref="ArgumentNullException"> /// g, edgePredicate or vertexPredicate are null /// </exception> public FilteredIncidenceGraph( IIncidenceGraph g, IEdgePredicate edgePredicate, IVertexPredicate vertexPredicate) : base(g, edgePredicate, vertexPredicate) { }
protected static void TryGetEdge_ImmutableGraph_Test( [NotNull] IMutableVertexAndEdgeSet <int, Edge <int> > wrappedGraph, [NotNull, InstantHandle] Func <IIncidenceGraph <int, SEquatableEdge <int> > > createGraph) { var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 2); var edge3 = new Edge <int>(1, 3); var edge4 = new Edge <int>(2, 2); var edge5 = new Edge <int>(2, 4); var edge6 = new Edge <int>(3, 1); wrappedGraph.AddVerticesAndEdgeRange(new[] { edge1, edge2, edge3, edge4, edge5, edge6 }); IIncidenceGraph <int, SEquatableEdge <int> > graph = createGraph(); Assert.IsFalse(graph.TryGetEdge(0, 10, out _)); Assert.IsFalse(graph.TryGetEdge(0, 1, out _)); Assert.IsTrue(graph.TryGetEdge(2, 4, out SEquatableEdge <int> gotEdge)); Assert.AreEqual(new SEquatableEdge <int>(2, 4), gotEdge); Assert.IsTrue(graph.TryGetEdge(2, 2, out gotEdge)); Assert.AreEqual(new SEquatableEdge <int>(2, 2), gotEdge); Assert.IsTrue(graph.TryGetEdge(1, 2, out gotEdge)); Assert.AreEqual(new SEquatableEdge <int>(1, 2), gotEdge); Assert.IsFalse(graph.TryGetEdge(2, 1, out _)); }
public ImplicitEdgeDepthFirstSearchAlgorithm( IAlgorithmComponent host, IIncidenceGraph <TVertex, TEdge> visitedGraph ) : base(host, visitedGraph) { }
protected static void ContainsEdge_SourceTarget_Test( [NotNull] IIncidenceGraph <int, Edge <int> > graph, [NotNull, InstantHandle] Action <Edge <int> > addVerticesAndEdge) { var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 3); var edge3 = new Edge <int>(2, 2); Assert.IsFalse(graph.ContainsEdge(1, 2)); Assert.IsFalse(graph.ContainsEdge(2, 1)); addVerticesAndEdge(edge1); Assert.IsTrue(graph.ContainsEdge(1, 2)); Assert.IsFalse(graph.ContainsEdge(2, 1)); addVerticesAndEdge(edge2); Assert.IsTrue(graph.ContainsEdge(1, 3)); Assert.IsFalse(graph.ContainsEdge(3, 1)); addVerticesAndEdge(edge3); Assert.IsTrue(graph.ContainsEdge(2, 2)); // Vertices is not present in the graph Assert.IsFalse(graph.ContainsEdge(0, 4)); Assert.IsFalse(graph.ContainsEdge(1, 4)); Assert.IsFalse(graph.ContainsEdge(4, 1)); }
protected static void TryGetEdge_Test( IIncidenceGraph <int, Edge <int> > graph, Action <IEnumerable <Edge <int> > > addVerticesAndEdgeRange) { var edge1 = new Edge <int>(1, 2); var edge2 = new Edge <int>(1, 2); var edge3 = new Edge <int>(1, 3); var edge4 = new Edge <int>(2, 2); var edge5 = new Edge <int>(2, 4); var edge6 = new Edge <int>(3, 1); addVerticesAndEdgeRange(new[] { edge1, edge2, edge3, edge4, edge5, edge6 }); Assert.IsFalse(graph.TryGetEdge(0, 10, out _)); Assert.IsFalse(graph.TryGetEdge(0, 1, out _)); Assert.IsTrue(graph.TryGetEdge(2, 4, out Edge <int> gotEdge)); Assert.AreSame(edge5, gotEdge); Assert.IsTrue(graph.TryGetEdge(2, 2, out gotEdge)); Assert.AreSame(edge4, gotEdge); Assert.IsTrue(graph.TryGetEdge(1, 2, out gotEdge)); Assert.AreSame(edge1, gotEdge); Assert.IsFalse(graph.TryGetEdge(2, 1, out _)); }
public SinkVertexPredicate(IIncidenceGraph <TVertex, TEdge> visitedGraph) { if (visitedGraph == null) { throw new ArgumentNullException("visitedGraph"); } this.visitedGraph = visitedGraph; }
/// <summary> /// Create a <see cref="sinkRecorderVisitor"/> instance. /// </summary> /// <param name="g">visited graph</param> /// <exception cref="ArgumentNullException">g is a null reference</exception> public SinkRecorderVisitor(IIncidenceGraph g) { if (g == null) { throw new ArgumentNullException("g"); } this.visitedGraph = g; }
public ImplicitDepthFirstSearchAlgorithm(IIncidenceGraph visitedGraph) { if (visitedGraph == null) { throw new ArgumentNullException("visitedGraph"); } this.visitedGraph = visitedGraph; }
protected static void ContainsEdge_SourceTarget_Test( [NotNull] GraphData <int, Edge <int> > data, [NotNull] IIncidenceGraph <int, Edge <int> > graph) { ContainsEdge_SourceTarget_GenericTest( data, graph.ContainsEdge); }
protected static void TryGetEdge_Test( [NotNull] GraphData <int, Edge <int> > data, [NotNull] IIncidenceGraph <int, Edge <int> > graph) { ContainsEdge_SourceTarget_GenericTest( data, (source, target) => graph.TryGetEdge(source, target, out _)); }
public SinkRecorderVisitor(IIncidenceGraph g) { this.sinks = new VertexCollection(); if (g == null) { throw new ArgumentNullException("g"); } this.visitedGraph = g; }
protected static void TryGetEdges_Throws_Test <TEdge>( [NotNull] IIncidenceGraph <TestVertex, TEdge> graph) where TEdge : IEdge <TestVertex> { // ReSharper disable AssignNullToNotNullAttribute Assert.Throws <ArgumentNullException>(() => graph.TryGetEdges(null, new TestVertex("v2"), out _)); Assert.Throws <ArgumentNullException>(() => graph.TryGetEdges(new TestVertex("v1"), null, out _)); Assert.Throws <ArgumentNullException>(() => graph.TryGetEdges(null, null, out _)); // ReSharper restore AssignNullToNotNullAttribute }
/// <summary> /// Create a <see cref="sinkRecorderVisitor"/> instance. /// </summary> /// <param name="g">visited graph</param> /// <param name="sinks">collection that will hold the sinks</param> /// <exception cref="ArgumentNullException">g is a null reference</exception> public SinkRecorderVisitor( IIncidenceGraph g, VertexCollection sinks) { if (g==null) throw new ArgumentNullException("g"); if (sinks==null) throw new ArgumentNullException("sinks"); this.visitedGraph = g; this.sinks = sinks; }
bool IIncidenceGraph <TVertex, TEdge> .ContainsEdge(TVertex source, TVertex target) { IIncidenceGraph <TVertex, TEdge> ithis = this; Contract.Requires(source != null); Contract.Requires(target != null); Contract.Requires(ithis.ContainsVertex(source)); Contract.Requires(ithis.ContainsVertex(target)); return(default(bool)); }
bool IIncidenceGraph <TVertex, TEdge> .TryGetEdges( TVertex source, TVertex target, out IEnumerable <TEdge> edges) { IIncidenceGraph <TVertex, TEdge> ithis = this; Contract.Requires(source != null); Contract.Requires(target != null); Contract.Requires(ithis.ContainsVertex(source)); Contract.Requires(ithis.ContainsVertex(target)); edges = null; return(default(bool)); }
bool IIncidenceGraph <TVertex, TEdge> .TryGetEdge( TVertex source, TVertex target, out TEdge edge) { IIncidenceGraph <TVertex, TEdge> ithis = this; //Contract.Requires(source != null); //Contract.Requires(target != null); //Contract.Requires(ithis.ContainsVertex(source)); //Contract.Requires(ithis.ContainsVertex(target)); edge = default(TEdge); return(default(bool)); }
/// <summary> /// Create a <see cref="sinkRecorderVisitor"/> instance. /// </summary> /// <param name="g">visited graph</param> /// <param name="sinks">collection that will hold the sinks</param> /// <exception cref="ArgumentNullException">g is a null reference</exception> public SinkRecorderVisitor( IIncidenceGraph g, VertexCollection sinks) { if (g == null) { throw new ArgumentNullException("g"); } if (sinks == null) { throw new ArgumentNullException("sinks"); } this.visitedGraph = g; this.sinks = sinks; }
protected static void TryGetEdges_Test( [NotNull] GraphData <int, Edge <int> > data, [NotNull] IIncidenceGraph <int, Edge <int> > graph) { data.CheckCalls(0); data.ShouldReturnValue = false; Assert.IsFalse(graph.TryGetEdges(0, 1, out _)); data.CheckCalls(1); data.ShouldReturnValue = true; Assert.IsTrue(graph.TryGetEdges(1, 2, out IEnumerable <Edge <int> > edges)); CollectionAssert.IsEmpty(edges); data.CheckCalls(1); data.ShouldReturnEdges = new[] { new Edge <int>(1, 2), new Edge <int>(1, 2) }; Assert.IsTrue(graph.TryGetEdges(1, 2, out edges)); CollectionAssert.AreEqual(data.ShouldReturnEdges, edges); data.CheckCalls(1); }
private ArrayList TopoSortAdjVertices(IVertex v, IIncidenceGraph g, VertexIntDictionary topo_ordering) // return adjacent vertices to "v" sorted in topological order { IEdgeEnumerator it = g.OutEdges(v).GetEnumerator(); bool valid = false; ArrayList adj = new ArrayList(); while (it.MoveNext()) { valid = true; adj.Add(it.Current.Target); } if (!valid) // no outgoing edges { return(adj); } CompareTopo ctopo = new CompareTopo(topo_ordering); SwapTopo stopo = new SwapTopo(); QuickSorter qs = new QuickSorter(ctopo, stopo); qs.Sort(adj); return(adj); }
/// <summary> /// Create a <see cref="sinkRecorderVisitor"/> instance. /// </summary> /// <param name="g">visited graph</param> /// <exception cref="ArgumentNullException">g is a null reference</exception> public SinkRecorderVisitor(IIncidenceGraph g) { if (g==null) throw new ArgumentNullException("g"); this.visitedGraph = g; }
public void TestOutDegree(IIncidenceGraph g) { }
public SinkVertexPredicate(IIncidenceGraph<TVertex, TEdge> visitedGraph) { Contract.Requires(visitedGraph != null); this.visitedGraph = visitedGraph; }
public void TestOutDegree() { IIncidenceGraph g = Generator.IncidenceGraph; }
public ImplicitEdgeDepthFirstSearchAlgorithm(IIncidenceGraph <TVertex, TEdge> visitedGraph) : this(null, visitedGraph) { }
private ArrayList TopoSortAdjVertices(IVertex v, IIncidenceGraph g, VertexIntDictionary topo_ordering) { IEdgeEnumerator enumerator = g.OutEdges(v).GetEnumerator(); bool flag = false; ArrayList list = new ArrayList(); while (enumerator.MoveNext()) { flag = true; list.Add(enumerator.get_Current().get_Target()); } if (flag) { CompareTopo topo = new CompareTopo(topo_ordering); SwapTopo topo2 = new SwapTopo(); new QuickSorter(topo, topo2).Sort(list); } return list; }
/// <summary> /// Initializes a new instance of the <see cref="ImplicitDepthFirstSearchAlgorithm{TVertex,TEdge}"/> class. /// </summary> /// <param name="host">Host to use if set, otherwise use this reference.</param> /// <param name="visitedGraph">Graph to visit.</param> public ImplicitDepthFirstSearchAlgorithm( [CanBeNull] IAlgorithmComponent host, [NotNull] IIncidenceGraph <TVertex, TEdge> visitedGraph) : base(host, visitedGraph) { }
/// <summary> /// Initializes a new instance of the <see cref="SinkVertexPredicate{TVertex,TEdge}"/> class. /// </summary> /// <param name="visitedGraph">Graph to consider.</param> public SinkVertexPredicate([NotNull] IIncidenceGraph <TVertex, TEdge> visitedGraph) { _visitedGraph = visitedGraph ?? throw new ArgumentNullException(nameof(visitedGraph)); }
// return adjacent vertices to "v" sorted in topological order private ArrayList TopoSortAdjVertices( IVertex v, IIncidenceGraph g, VertexIntDictionary topo_ordering ) { IEdgeEnumerator it = g.OutEdges(v).GetEnumerator(); bool valid = false; ArrayList adj = new ArrayList(); while(it.MoveNext()) { valid = true; adj.Add(it.Current.Target); } if(!valid) // no outgoing edges return adj; CompareTopo ctopo = new CompareTopo(topo_ordering); SwapTopo stopo = new SwapTopo(); QuickSorter qs = new QuickSorter(ctopo, stopo); qs.Sort(adj); return adj; }
private static void RunImplicitDFSAndCheck <TVertex, TEdge>( [NotNull] IIncidenceGraph <TVertex, TEdge> graph, [NotNull] TVertex sourceVertex, int maxDepth = int.MaxValue) where TEdge : IEdge <TVertex> { var parents = new Dictionary <TVertex, TVertex>(); var discoverTimes = new Dictionary <TVertex, int>(); var finishTimes = new Dictionary <TVertex, int>(); int time = 0; var dfs = new ImplicitDepthFirstSearchAlgorithm <TVertex, TEdge>(graph) { MaxDepth = maxDepth }; dfs.StartVertex += vertex => { Assert.IsFalse(parents.ContainsKey(vertex)); parents[vertex] = vertex; }; dfs.DiscoverVertex += vertex => { Assert.AreEqual(GraphColor.Gray, dfs.VerticesColors[vertex]); Assert.AreEqual(GraphColor.Gray, dfs.VerticesColors[parents[vertex]]); discoverTimes[vertex] = time++; }; dfs.ExamineEdge += edge => { Assert.AreEqual(GraphColor.Gray, dfs.VerticesColors[edge.Source]); }; dfs.TreeEdge += edge => { parents[edge.Target] = edge.Source; }; dfs.BackEdge += edge => { Assert.AreEqual(GraphColor.Gray, dfs.VerticesColors[edge.Target]); }; dfs.ForwardOrCrossEdge += edge => { Assert.AreEqual(GraphColor.Black, dfs.VerticesColors[edge.Target]); }; dfs.FinishVertex += vertex => { Assert.AreEqual(GraphColor.Black, dfs.VerticesColors[vertex]); finishTimes[vertex] = time++; }; dfs.Compute(sourceVertex); // Check if (maxDepth == int.MaxValue) { Assert.AreEqual(discoverTimes.Count, finishTimes.Count); } else { Assert.GreaterOrEqual(discoverTimes.Count, finishTimes.Count); } TVertex[] exploredVertices = finishTimes.Keys.ToArray(); foreach (TVertex u in exploredVertices) { foreach (TVertex v in exploredVertices) { if (!u.Equals(v)) { Assert.IsTrue( finishTimes[u] < discoverTimes[v] || finishTimes[v] < discoverTimes[u] || (discoverTimes[v] < discoverTimes[u] && finishTimes[u] < finishTimes[v] && IsDescendant(parents, u, v)) || (discoverTimes[u] < discoverTimes[v] && finishTimes[v] < finishTimes[u] && IsDescendant(parents, v, u))); } } } }