158 lines
5.4 KiB
Java
158 lines
5.4 KiB
Java
|
/*This is a java program to implement Edmond’s Algorithm for maximum cardinality matching. In graph theory, a branch of mathematics, Edmonds’ algorithm or Chu–Liu/Edmonds’ algorithm is an algorithm for finding a maximum or minimum optimum branchings. This is similar to the minimum spanning tree problem which concerns undirected graphs. However, when nodes are connected by weighted edges that are directed, a minimum spanning tree algorithm cannot be used.*/
|
|||
|
|
|||
|
|
|||
|
import java.util.ArrayList;
|
|||
|
import java.util.Arrays;
|
|||
|
import java.util.List;
|
|||
|
import java.util.Scanner;
|
|||
|
|
|||
|
public class EdmondsMaximumCardinalityMatching
|
|||
|
{
|
|||
|
static int lca(int[] match, int[] base, int[] p, int a, int b)
|
|||
|
{
|
|||
|
boolean[] used = new boolean[match.length];
|
|||
|
while (true)
|
|||
|
{
|
|||
|
a = base[a];
|
|||
|
used[a] = true;
|
|||
|
if (match[a] == -1)
|
|||
|
break;
|
|||
|
a = p[match[a]];
|
|||
|
}
|
|||
|
while (true)
|
|||
|
{
|
|||
|
b = base[b];
|
|||
|
if (used[b])
|
|||
|
return b;
|
|||
|
b = p[match[b]];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void markPath(int[] match, int[] base, boolean[] blossom, int[] p,
|
|||
|
int v, int b, int children)
|
|||
|
{
|
|||
|
for (; base[v] != b; v = p[match[v]])
|
|||
|
{
|
|||
|
blossom[base[v]] = blossom[base[match[v]]] = true;
|
|||
|
p[v] = children;
|
|||
|
children = match[v];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static int findPath(List<Integer>[] graph, int[] match, int[] p, int root)
|
|||
|
{
|
|||
|
int n = graph.length;
|
|||
|
boolean[] used = new boolean[n];
|
|||
|
Arrays.fill(p, -1);
|
|||
|
int[] base = new int[n];
|
|||
|
for (int i = 0; i < n; ++i)
|
|||
|
base[i] = i;
|
|||
|
used[root] = true;
|
|||
|
int qh = 0;
|
|||
|
int qt = 0;
|
|||
|
int[] q = new int[n];
|
|||
|
q[qt++] = root;
|
|||
|
while (qh < qt)
|
|||
|
{
|
|||
|
int v = q[qh++];
|
|||
|
for (int to : graph[v])
|
|||
|
{
|
|||
|
if (base[v] == base[to] || match[v] == to)
|
|||
|
continue;
|
|||
|
if (to == root || match[to] != -1 && p[match[to]] != -1)
|
|||
|
{
|
|||
|
int curbase = lca(match, base, p, v, to);
|
|||
|
boolean[] blossom = new boolean[n];
|
|||
|
markPath(match, base, blossom, p, v, curbase, to);
|
|||
|
markPath(match, base, blossom, p, to, curbase, v);
|
|||
|
for (int i = 0; i < n; ++i)
|
|||
|
if (blossom[base[i]])
|
|||
|
{
|
|||
|
base[i] = curbase;
|
|||
|
if (!used[i])
|
|||
|
{
|
|||
|
used[i] = true;
|
|||
|
q[qt++] = i;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if (p[to] == -1)
|
|||
|
{
|
|||
|
p[to] = v;
|
|||
|
if (match[to] == -1)
|
|||
|
return to;
|
|||
|
to = match[to];
|
|||
|
used[to] = true;
|
|||
|
q[qt++] = to;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
public static int maxMatching(List<Integer>[] graph)
|
|||
|
{
|
|||
|
int n = graph.length;
|
|||
|
int[] match = new int[n];
|
|||
|
Arrays.fill(match, -1);
|
|||
|
int[] p = new int[n];
|
|||
|
for (int i = 0; i < n; ++i)
|
|||
|
{
|
|||
|
if (match[i] == -1)
|
|||
|
{
|
|||
|
int v = findPath(graph, match, p, i);
|
|||
|
while (v != -1)
|
|||
|
{
|
|||
|
int pv = p[v];
|
|||
|
int ppv = match[pv];
|
|||
|
match[v] = pv;
|
|||
|
match[pv] = v;
|
|||
|
v = ppv;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
int matches = 0;
|
|||
|
for (int i = 0; i < n; ++i)
|
|||
|
if (match[i] != -1)
|
|||
|
++matches;
|
|||
|
return matches / 2;
|
|||
|
}
|
|||
|
|
|||
|
@SuppressWarnings("unchecked")
|
|||
|
public static void main(String[] args)
|
|||
|
{
|
|||
|
Scanner sc = new Scanner(System.in);
|
|||
|
System.out.println("Enter the number of vertices: ");
|
|||
|
int v = sc.nextInt();
|
|||
|
System.out.println("Enter the number of edges: ");
|
|||
|
int e = sc.nextInt();
|
|||
|
List<Integer>[] g = new List[v];
|
|||
|
for (int i = 0; i < v; i++)
|
|||
|
{
|
|||
|
g[i] = new ArrayList<Integer>();
|
|||
|
}
|
|||
|
System.out.println("Enter all the edges: <from> <to>");
|
|||
|
for (int i = 0; i < e; i++)
|
|||
|
{
|
|||
|
g[sc.nextInt()].add(sc.nextInt());
|
|||
|
}
|
|||
|
System.out.println("Maximum matching for the given graph is: "
|
|||
|
+ maxMatching(g));
|
|||
|
sc.close();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Enter the number of vertices:
|
|||
|
6
|
|||
|
Enter the number of edges:
|
|||
|
7
|
|||
|
Enter all the edges: <from> <to>
|
|||
|
0 1
|
|||
|
1 2
|
|||
|
1 3
|
|||
|
3 4
|
|||
|
4 5
|
|||
|
5 3
|
|||
|
5 2
|
|||
|
Maximum matching for the given graph is: 3
|