// Pass in a maximal set of edge-disjoint paths from `startVertex` to some end point // Returns a cut: a minimal list of (directed) edges to delete to disconnect `startVertex` from the end point. public static HashSet <Tuple <T, T> > FindCutEDP <T>(this IGraphEdges <T> graph, T startVertex, HashSet <Tuple <T, T> > pathEdges) { var accessible = new HashSet <T>( from pair in graph.AccessibleVerticesEDP(startVertex, pathEdges) select pair.Item1); return(new HashSet <Tuple <T, T> >( from start in accessible from end in graph.GetNeighbours(start) where !accessible.Contains(end) select Tuple.Create(start, end))); }
// New implementation, using Enumerable from above (so doesn't directly form the "residual graph"). private static HashSet <Tuple <T, T> > EdgeDisjointPaths1 <T>(this IGraphEdges <T> graph, T startVertex, T to) { var currentPaths = new HashSet <Tuple <T, T> >(); if (Eq(startVertex, to)) { return(currentPaths); } while (true) { // lookup[vertex] = parent of vertex; so there is an edge lookup[vertex] -> vertex var lookup = new Dictionary <T, T>(); bool foundTo = false; foreach (var vertexPair in graph.AccessibleVerticesEDP(startVertex, currentPaths)) { // Edge from parent -> vertex var vertex = vertexPair.Item1; var parent = vertexPair.Item2; if (!Eq(vertex, startVertex)) { lookup[vertex] = parent; } if (Eq(vertex, to)) { foundTo = true; break; } } if (!foundTo) { break; } T current = to; while (!Eq(startVertex, current)) { var edge = Tuple.Create(lookup[current], current); var revEdge = Tuple.Create(current, lookup[current]); current = lookup[current]; if (!currentPaths.Remove(revEdge)) { currentPaths.Add(edge); } } } return(currentPaths); }