274 lines
7.0 KiB
Java
274 lines
7.0 KiB
Java
/*This is a java program check if the graph contains any weak link (articulation point). A vertex in an undirected connected graph is an articulation point (or cut vertex) iff removing it (and edges through it) disconnects the graph. Articulation points represent vulnerabilities in a connected network – single points whose failure would split the network into 2 or more disconnected components. They are useful for designing reliable networks.*/
|
||
|
||
|
||
import java.util.Iterator;
|
||
import java.util.NoSuchElementException;
|
||
import java.util.Scanner;
|
||
import java.util.Stack;
|
||
|
||
class Bag<Item> implements Iterable<Item>
|
||
{
|
||
private int N; // number of elements in bag
|
||
private Node<Item> first; // beginning of bag
|
||
|
||
// helper linked list class
|
||
private static class Node<Item>
|
||
{
|
||
private Item item;
|
||
private Node<Item> next;
|
||
}
|
||
|
||
public Bag()
|
||
{
|
||
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
|
||
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 APGraph
|
||
{
|
||
private final int V;
|
||
private int E;
|
||
private Bag<Integer>[] adj;
|
||
|
||
public APGraph(int V)
|
||
{
|
||
if (V < 0)
|
||
throw new IllegalArgumentException(
|
||
"Number of vertices must be nonnegative");
|
||
this.V = V;
|
||
this.E = 0;
|
||
adj = (Bag<Integer>[]) new Bag[V];
|
||
for (int v = 0; v < V; v++)
|
||
{
|
||
adj[v] = new Bag<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");
|
||
}
|
||
for (int i = 0; i < E; i++)
|
||
{
|
||
int v = sc.nextInt();
|
||
int w = sc.nextInt();
|
||
addEdge(v, w);
|
||
}
|
||
sc.close();
|
||
}
|
||
|
||
public APGraph(APGraph 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 ArticulationPoints
|
||
{
|
||
private int[] low;
|
||
private int[] pre;
|
||
private int cnt;
|
||
private boolean[] articulation;
|
||
|
||
public ArticulationPoints(APGraph 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(APGraph 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: ");
|
||
APGraph G = new APGraph(sc.nextInt());
|
||
System.out.println(G);
|
||
ArticulationPoints bic = new ArticulationPoints(G);
|
||
System.out.println("Atriculation points: ");
|
||
for (int v = 0; v < G.V(); v++)
|
||
if (bic.isArticulation(v))
|
||
System.out.println(v);
|
||
sc.close();
|
||
}
|
||
}
|
||
|
||
/*
|
||
Enter the number of vertices:
|
||
6
|
||
Enter the number of edges:
|
||
7
|
||
|
||
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
|
||
|
||
Atriculation points:
|
||
1 |