Esempio n. 1
0
        public void Run()
        {
            // create random bipartite graph with V vertices and E edges; then add F random edges
            const int v1 = 10;
            const int v2 = 10;
            const int e  = 20;
            const int f  = 5;

            // create random bipartite graph with V1 vertices on left side,
            // V2 vertices on right side, and E edges; then add F random edges
            var graph = GraphGenerator.Bipartite(v1, v2, e);

            for (var i = 0; i < f; i++)
            {
                var v = StdRandom.Uniform(v1 + v2);
                var w = StdRandom.Uniform(v1 + v2);
                graph.AddEdge(v, w);
            }

            Console.WriteLine(graph);


            var b = new BipartiteX(graph);

            if (b.IsBipartite())
            {
                Console.WriteLine("Graph is bipartite");
                for (var v = 0; v < graph.V; v++)
                {
                    Console.WriteLine($"{v}: {b.Color(v)}");
                }
            }
            else
            {
                Console.WriteLine("Graph has an odd-length cycle: ");
                foreach (int x in b.OddCycle())
                {
                    Console.Write($"{x} ");
                }
                Console.WriteLine();
            }

            Console.ReadLine();
        }
Esempio n. 2
0
    private int[] distTo;                // distTo[v] = number of edges on shortest path to v

    /**
     * Determines a maximum matching (and a minimum vertex cover)
     * in a bipartite graph.
     *
     * @param  G the bipartite graph
     * @throws IllegalArgumentException if {@code G} is not bipartite
     */
    public HopcroftKarp(Graph G) {
        bipartition = new BipartiteX(G);
        if (!bipartition.isBipartite()) {
            throw new IllegalArgumentException("graph is not bipartite");
        }

        // initialize empty matching
        this.V = G.V();
        mate = new int[V];
        for (int v = 0; v < V; v++)
            mate[v] = UNMATCHED;

        // the call to hasAugmentingPath() provides enough info to reconstruct level graph
        while (hasAugmentingPath(G)) {

            // to be able to iterate over each adjacency list, keeping track of which
            // vertex in each adjacency list needs to be explored next
            Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()];
            for (int v = 0; v < G.V(); v++)
                adj[v] = G.adj(v).iterator();

            // for each unmatched vertex s on one side of bipartition
            for (int s = 0; s < V; s++) {
                if (isMatched(s) || !bipartition.color(s)) continue;   // or use distTo[s] == 0

                // find augmenting path from s using nonrecursive DFS
                Stack<Integer> path = new Stack<Integer>();
                path.push(s);
                while (!path.isEmpty()) {
                    int v = path.peek();

                    // retreat, no more edges in level graph leaving v
                    if (!adj[v].hasNext())
                        path.pop();

                    // advance
                    else {
                        // process edge v-w only if it is an edge in level graph
                        int w = adj[v].next();
                        if (!isLevelGraphEdge(v, w)) continue;

                        // add w to augmenting path
                        path.push(w);

                        // augmenting path found: update the matching
                        if (!isMatched(w)) {
                            // StdOut.println("augmenting path: " + toString(path));

                            while (!path.isEmpty()) {
                                int x = path.pop();
                                int y = path.pop();
                                mate[x] = y;
                                mate[y] = x;
                            }
                            cardinality++;
                        }
                    }
                }
            }
        }

        // also find a min vertex cover
        inMinVertexCover = new boolean[V];
        for (int v = 0; v < V; v++) {
            if (bipartition.color(v) && !marked[v]) inMinVertexCover[v] = true;
            if (!bipartition.color(v) && marked[v]) inMinVertexCover[v] = true;
        }

        assert certifySolution(G);
    }