-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathConnectedComponents.java
146 lines (124 loc) · 4.63 KB
/
ConnectedComponents.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.graphs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Find the connected component in graph. Two vertices are reachable from one to
* the second if and only if they are in the same connected components.
*
* @author STEPHANE MIGUEL KAKANAKOU (Skakanakou@gmail.com)
*
*/
public class ConnectedComponents {
/**
* Given a graph G, we want to find and output the connected components in
* the graph. If G is an undirected graph, the function return the connected
* components. If G is a directed graph, the function return the strongly
* connected components.
*
* @param graph
* The given graph.
* @return If G is an undirected graph, the function return the connected
* components. If G is a directed graph, this graph return the
* strongly connected components.
*/
public static List<List<Integer>> getConnectedComponents(GraphAdjacencyListRepresentation graph) {
if (graph == null)
throw new IllegalArgumentException("Invalid Argument");
if (graph.isDirectedGraph())
return getConnectedComponentsForDirectedGraph(graph);
else
return getConnectedComponentsForUndirectedGraph(graph);
}
private static List<List<Integer>> getConnectedComponentsForDirectedGraph(GraphAdjacencyListRepresentation graph) {
int V_Size = graph.getV_Size();
GraphAdjacencyListRepresentation reverseGraph = graph.reverseGraph();
NodePostOrder[] postOrder = new NodePostOrder[V_Size];
boolean[] visited = new boolean[V_Size];
// run dfs on the reverse graph
int po = 0;
for (int u = 0; u < V_Size; u++) {
if (!visited[u]) {
po = explore(reverseGraph, u, visited, po, postOrder);
}
}
// sort vertices in the reverse order of their post order
Arrays.sort(postOrder, Collections.reverseOrder());
// Explore the vertices in the reverse order of their post order
int[] cc = new int[V_Size];
Arrays.fill(cc, -1);
int ccNum = 0;
for (int u = 0; u < V_Size; u++) {
if (cc[postOrder[u].vertice] == -1) {
explore(graph, postOrder[u].vertice, ccNum, cc);
ccNum++;
}
}
List<List<Integer>> stronglyConnectedComponents = new ArrayList<>();
for (int i = 0; i < ccNum; i++) {
stronglyConnectedComponents.add(new ArrayList<>());
}
for (int u = 0; u < V_Size; u++) {
stronglyConnectedComponents.get(cc[u]).add(u);
}
return stronglyConnectedComponents;
}
private static List<List<Integer>> getConnectedComponentsForUndirectedGraph(
GraphAdjacencyListRepresentation graph) {
int ccNum = 0;
int V_Size = graph.getV_Size();
int[] cc = new int[V_Size];
Arrays.fill(cc, -1);
for (int u = 0; u < V_Size; u++) {
if (cc[u] == -1) {
explore(graph, u, ccNum, cc);
ccNum++;
}
}
List<List<Integer>> connectedComponents = new ArrayList<>();
for (int i = 0; i < ccNum; i++) {
connectedComponents.add(new ArrayList<>());
}
for (int u = 0; u < V_Size; u++) {
connectedComponents.get(cc[u]).add(u);
}
return connectedComponents;
}
private static int explore(GraphAdjacencyListRepresentation graph, int u, boolean[] visited, int num,
NodePostOrder[] postOrder) {
visited[u] = true;
int po = num;
for (int v : graph.getAdjNode(u)) {
if (!visited[v]) {
po = explore(graph, v, visited, po + 1, postOrder);
}
}
postOrder[u] = new NodePostOrder(u, po);
return po + 1;
}
private static void explore(GraphAdjacencyListRepresentation graph, int u, int ccNum, int[] cc) {
cc[u] = ccNum;
for (int v : graph.getAdjNode(u)) {
if (cc[v] == -1) {
explore(graph, v, ccNum, cc);
}
}
}
private static class NodePostOrder implements Comparable<NodePostOrder> {
int vertice;
int postOrder;
public NodePostOrder(int v, int po) {
vertice = v;
postOrder = po;
}
@Override
public int compareTo(NodePostOrder other) {
if (this.postOrder < other.postOrder)
return -1;
else if (this.postOrder > other.postOrder)
return 1;
return 0;
}
}
}