277 lines
7.0 KiB
Java
277 lines
7.0 KiB
Java
|
/*This is a java program to find the vertex connectivity of a graph. Vertex connectivity simply means number of articulations points in a graph, articulation points are vertices of a graph whem removed makes graph disconnected.*/
|
||
|
|
||
|
|
||
|
import java.util.Iterator;
|
||
|
import java.util.NoSuchElementException;
|
||
|
import java.util.Scanner;
|
||
|
import java.util.Stack;
|
||
|
|
||
|
class VCBag<Item> implements Iterable<Item>
|
||
|
{
|
||
|
private int N; // number of elements in VCBag
|
||
|
private Node<Item> first; // beginning of VCBag
|
||
|
|
||
|
// helper linked list class
|
||
|
private static class Node<Item>
|
||
|
{
|
||
|
private Item item;
|
||
|
private Node<Item> next;
|
||
|
}
|
||
|
|
||
|
public VCBag()
|
||
|
{
|
||
|
first = null;
|
||
|
N = 0;
|
||
|
}
|
||
|
|
||
|
public boolean isEmpty()
|
||
|
{
|
||
|
return first == null;
|
||
|
}
|
||
|
|
||
|
public int size()
|
||
|
{
|
||
|
return N;
|
||
|
}
|
||
|
|
||
|
public void add(Item item)
|
||
|
{
|
||
|
Node<Item> oldfirst = first;
|
||
|
first = new Node<Item>();
|
||
|
first.item = item;
|
||
|
first.next = oldfirst;
|
||
|
N++;
|
||
|
}
|
||
|
|
||
|
public Iterator<Item> iterator()
|
||
|
{
|
||
|
return new ListIterator<Item>(first);
|
||
|
}
|
||
|
|
||
|
// an iterator, doesn't implement remove() since it's optional
|
||
|
@SuppressWarnings("hiding")
|
||
|
private class ListIterator<Item> implements Iterator<Item>
|
||
|
{
|
||
|
private Node<Item> current;
|
||
|
|
||
|
public ListIterator(Node<Item> first)
|
||
|
{
|
||
|
current = first;
|
||
|
}
|
||
|
|
||
|
public boolean hasNext()
|
||
|
{
|
||
|
return current != null;
|
||
|
}
|
||
|
|
||
|
public void remove()
|
||
|
{
|
||
|
throw new UnsupportedOperationException();
|
||
|
}
|
||
|
|
||
|
public Item next()
|
||
|
{
|
||
|
if (!hasNext())
|
||
|
throw new NoSuchElementException();
|
||
|
Item item = current.item;
|
||
|
current = current.next;
|
||
|
return item;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class VCGraph
|
||
|
{
|
||
|
private final int V;
|
||
|
private int E;
|
||
|
private VCBag<Integer>[] adj;
|
||
|
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public VCGraph(int V)
|
||
|
{
|
||
|
if (V < 0)
|
||
|
throw new IllegalArgumentException(
|
||
|
"Number of vertices must be nonnegative");
|
||
|
this.V = V;
|
||
|
this.E = 0;
|
||
|
adj = (VCBag<Integer>[]) new VCBag[V];
|
||
|
for (int v = 0; v < V; v++)
|
||
|
{
|
||
|
adj[v] = new VCBag<Integer>();
|
||
|
}
|
||
|
System.out.println("Enter the number of edges: ");
|
||
|
Scanner sc = new Scanner(System.in);
|
||
|
int E = sc.nextInt();
|
||
|
if (E < 0)
|
||
|
{
|
||
|
sc.close();
|
||
|
throw new IllegalArgumentException(
|
||
|
"Number of edges must be nonnegative");
|
||
|
}
|
||
|
System.out.println("Enter the edges: <from> <to>");
|
||
|
for (int i = 0; i < E; i++)
|
||
|
{
|
||
|
int v = sc.nextInt();
|
||
|
int w = sc.nextInt();
|
||
|
addEdge(v, w);
|
||
|
}
|
||
|
sc.close();
|
||
|
}
|
||
|
|
||
|
public VCGraph(VCGraph G)
|
||
|
{
|
||
|
this(G.V());
|
||
|
this.E = G.E();
|
||
|
for (int v = 0; v < G.V(); v++)
|
||
|
{
|
||
|
// reverse so that adjacency list is in same order as original
|
||
|
Stack<Integer> reverse = new Stack<Integer>();
|
||
|
for (int w : G.adj[v])
|
||
|
{
|
||
|
reverse.push(w);
|
||
|
}
|
||
|
for (int w : reverse)
|
||
|
{
|
||
|
adj[v].add(w);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int V()
|
||
|
{
|
||
|
return V;
|
||
|
}
|
||
|
|
||
|
public int E()
|
||
|
{
|
||
|
return E;
|
||
|
}
|
||
|
|
||
|
public void addEdge(int v, int w)
|
||
|
{
|
||
|
if (v < 0 || v >= V)
|
||
|
throw new IndexOutOfBoundsException();
|
||
|
if (w < 0 || w >= V)
|
||
|
throw new IndexOutOfBoundsException();
|
||
|
E++;
|
||
|
adj[v].add(w);
|
||
|
adj[w].add(v);
|
||
|
}
|
||
|
|
||
|
public Iterable<Integer> adj(int v)
|
||
|
{
|
||
|
if (v < 0 || v >= V)
|
||
|
throw new IndexOutOfBoundsException();
|
||
|
return adj[v];
|
||
|
}
|
||
|
|
||
|
public String toString()
|
||
|
{
|
||
|
StringBuilder s = new StringBuilder();
|
||
|
String NEWLINE = System.getProperty("line.separator");
|
||
|
s.append(V + " vertices, " + E + " edges " + NEWLINE);
|
||
|
for (int v = 0; v < V; v++)
|
||
|
{
|
||
|
s.append(v + ": ");
|
||
|
for (int w : adj[v])
|
||
|
{
|
||
|
s.append(w + " ");
|
||
|
}
|
||
|
s.append(NEWLINE);
|
||
|
}
|
||
|
return s.toString();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class VertexConnectivity
|
||
|
{
|
||
|
private int[] low;
|
||
|
private int[] pre;
|
||
|
private int cnt;
|
||
|
private boolean[] articulation;
|
||
|
|
||
|
public VertexConnectivity(VCGraph G)
|
||
|
{
|
||
|
low = new int[G.V()];
|
||
|
pre = new int[G.V()];
|
||
|
articulation = new boolean[G.V()];
|
||
|
for (int v = 0; v < G.V(); v++)
|
||
|
low[v] = -1;
|
||
|
for (int v = 0; v < G.V(); v++)
|
||
|
pre[v] = -1;
|
||
|
for (int v = 0; v < G.V(); v++)
|
||
|
if (pre[v] == -1)
|
||
|
dfs(G, v, v);
|
||
|
}
|
||
|
|
||
|
private void dfs(VCGraph G, int u, int v)
|
||
|
{
|
||
|
int children = 0;
|
||
|
pre[v] = cnt++;
|
||
|
low[v] = pre[v];
|
||
|
for (int w : G.adj(v))
|
||
|
{
|
||
|
if (pre[w] == -1)
|
||
|
{
|
||
|
children++;
|
||
|
dfs(G, v, w);
|
||
|
// update low number
|
||
|
low[v] = Math.min(low[v], low[w]);
|
||
|
// non-root of DFS is an articulation point if low[w] >= pre[v]
|
||
|
if (low[w] >= pre[v] && u != v)
|
||
|
articulation[v] = true;
|
||
|
}
|
||
|
// update low number - ignore reverse of edge leading to v
|
||
|
else if (w != u)
|
||
|
low[v] = Math.min(low[v], pre[w]);
|
||
|
}
|
||
|
// root of DFS is an articulation point if it has more than 1 child
|
||
|
if (u == v && children > 1)
|
||
|
articulation[v] = true;
|
||
|
}
|
||
|
|
||
|
// is vertex v an articulation point?
|
||
|
public boolean isArticulation(int v)
|
||
|
{
|
||
|
return articulation[v];
|
||
|
}
|
||
|
|
||
|
// test client
|
||
|
public static void main(String[] args)
|
||
|
{
|
||
|
Scanner sc = new Scanner(System.in);
|
||
|
System.out.println("Enter the number of vertices: ");
|
||
|
VCGraph G = new VCGraph(sc.nextInt());
|
||
|
System.out.println(G);
|
||
|
VertexConnectivity bic = new VertexConnectivity(G);
|
||
|
int count = 0;
|
||
|
for (int v = 0; v < G.V(); v++)
|
||
|
if (bic.isArticulation(v))
|
||
|
count++;
|
||
|
System.out.println("Vertex Connectivity: " + count);
|
||
|
sc.close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Enter the number of vertices:
|
||
|
6
|
||
|
Enter the number of edges:
|
||
|
7
|
||
|
Enter the edges: <from> <to>
|
||
|
0 1
|
||
|
1 2
|
||
|
1 3
|
||
|
3 4
|
||
|
4 5
|
||
|
5 3
|
||
|
5 2
|
||
|
6 vertices, 7 edges
|
||
|
0: 1
|
||
|
1: 3 2 0
|
||
|
2: 5 1
|
||
|
3: 5 4 1
|
||
|
4: 5 3
|
||
|
5: 2 3 4
|
||
|
|
||
|
Vertex Connectivity: 1
|