Ejemplo n.º 1
0
        // Call with `paths` being a family of paths from startVertex to some end point.  This family should
        // be vertex-disjoint and maximal.
        // Returns a cut.
        public static List <T> FindCutVDP <T>(this IGraphEdges <T> graph, T startVertex, List <List <T> > paths)
        {
            var usedEdges = new HashSet <Tuple <T, T> >();

            foreach (var path in paths)
            {
                for (int i = 0; i < path.Count() - 1; ++i)
                {
                    usedEdges.Add(Tuple.Create(path[i], path[i + 1]));
                }
            }
            var accessible = new HashSet <T>(from pair in graph.AccessibleVerticesVDP(startVertex, usedEdges) select pair.Item1);
            var cut        = new HashSet <T>(
                from vertex in accessible
                from v in graph.GetNeighbours(vertex)
                where !accessible.Contains(v)
                select vertex);

            if (cut.Remove(startVertex))
            {
                foreach (var v in graph.GetNeighbours(startVertex))
                {
                    if (!accessible.Contains(v))
                    {
                        cut.Add(v);
                    }
                }
            }
            return(new List <T>(cut));
        }
Ejemplo n.º 2
0
        // Variant which allows us to start with some existing paths: useful if e.g. the application
        // comes with some "obvious" paths we can start from.  This assumes that `startVertex` and `to`
        // are not equal or neighbours.
        public static List <List <T> > FindVertexDisjointPaths1 <T>(this IGraphEdges <T> graph, T startVertex, T to, HashSet <Tuple <T, T> > edges)
        {
            var usedEdges = new HashSet <Tuple <T, T> >(edges);

            while (true)
            {
                // newPath[vertex] == predecessor of vertex; i.e. edge from newPath[vertex] to vertex
                var lookup = new Dictionary <T, T>();
                // Problem: It's possible to visit the same vertex twice (thanks to non-local walking rules)
                var  backup     = new Dictionary <T, T>();
                bool canReachTo = false;
                foreach (var vertexPair in graph.AccessibleVerticesVDP(startVertex, usedEdges))
                {
                    // Edge from vertexPair.Item2 to vertexPair.Item1
                    if (Eq(startVertex, vertexPair.Item1))
                    {
                        continue;
                    }
                    if (lookup.ContainsKey(vertexPair.Item1))
                    {
                        backup[vertexPair.Item1] = lookup[vertexPair.Item1];
                    }
                    lookup[vertexPair.Item1] = vertexPair.Item2;
                    if (Eq(to, vertexPair.Item1))
                    {
                        canReachTo = true; break;
                    }
                }
                if (!canReachTo)
                {
                    break;
                }
                var vertex = to;
                while (!Eq(vertex, startVertex))
                {
                    var edge    = Tuple.Create(lookup[vertex], vertex);
                    var revEdge = Tuple.Create(vertex, lookup[vertex]);
                    if (!usedEdges.Remove(revEdge))
                    {
                        usedEdges.Add(edge);
                    }
                    if (backup.ContainsKey(vertex))
                    {
                        T tmp = lookup[vertex];
                        lookup[vertex] = backup[vertex];
                        vertex         = tmp;
                    }
                    else
                    {
                        vertex = lookup[vertex];
                    }
                }
            }
            // Assemble Paths
            return(ConvertEdgesToPaths(usedEdges, startVertex, to));
        }