-
Notifications
You must be signed in to change notification settings - Fork 368
/
Copy pathTarjan.java
159 lines (130 loc) · 4.42 KB
/
Tarjan.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
147
148
149
150
151
152
153
154
155
156
157
158
159
/* I will use Tarjan's Algorithm to find the bridges
So, what is a bridge -> A bridge of a connected graph is a graph edge whose removal disconnects the graph
So if we remove the bridge then the graph will be converted into multiple components.
e.g. 1 ←-----→ 3 ←----→ 4
↑ ↗ ↑
| ↗ |
| ↗ |
↓ ↙ ↓
2 5
In the above bidirectional graph, if we remove edge 3-4 then the graph will be broken into two different components so, we can say 3-4 is a bridge.
T.c.=> O(V+E)
Auxiliary Space: O(V)
*/
import java.util.ArrayList;
import java.util.List;
public class Edge {
int u;
int v;
public Edge(int u, int v) {
this.u = u;
this.v = v;
}
}
public class DFSData {
int node;
int parent;
public DFSData(int node, int parent) {
this.node = node;
this.parent = parent;
}
}
public class Graph {
List<Edge> edges;
int numEdges;
List<Integer>[] adjList;
int[] adjListSize;
int[] tin;
int[] low;
int timer;
boolean[] visited;
public Graph(int numNodes) {
edges = new ArrayList<>();
numEdges = 0;
adjList = new ArrayList[numNodes];
adjListSize = new int[numNodes];
tin = new int[numNodes];
low = new int[numNodes];
timer = 1;
visited = new boolean[numNodes];
for (int i = 0; i < numNodes; i++) {
adjList[i] = new ArrayList<>();
adjListSize[i] = 0;
visited[i] = false;
}
}
public void addEdge(int u, int v) {
Edge edge = new Edge(u, v);
edges.add(edge);
numEdges++;
adjList[u].add(v);
adjList[v].add(u);
adjListSize[u]++;
adjListSize[v]++;
}
public void dfs(int node, int parent, DFSData[] dfsData, int[] numBridges, Edge[] bridges) {
visited[node] = true;
tin[node] = low[node] = timer++;
// Traverse all adjacent nodes of the current node
for (int i = 0; i < adjListSize[node]; i++) {
int child = adjList[node].get(i);
// Skip the parent node to avoid going back in the same path
if (child == parent)
continue;
// If the child node is not visited, perform DFS on it
if (!visited[child]) {
// Store the DFS data of the child node
dfsData[child] = new DFSData(child, node);
dfs(child, node, dfsData, numBridges, bridges);
// Update the low value of the current node based on the child's low value
low[node] = Math.min(low[node], low[child]);
// If the low value of the child is greater than the tin value of the current node,
// it means the edge is a bridge
if (low[child] > tin[node]) {
bridges[numBridges[0]] = new Edge(node, child);
numBridges[0]++;
}
} else {
// If the child node is already visited, update the low value of the current node
// based on the child's tin value
low[node] = Math.min(low[node], tin[child]);
}
}
}
public Edge[] findBridges() {
DFSData[] dfsData = new DFSData[adjList.length];
int[] numBridges = {0};
Edge[] bridges = new Edge[numEdges];
// Perform DFS on the graph starting from node 0
dfs(0, -1, dfsData, numBridges, bridges);
return bridges;
}
}
public class TarjanAlgorithm {
public static void main(String[] args) {
int numNodes = 5;
Graph graph = new Graph(numNodes);
graph.addEdge(0, 1);
graph.addEdge(1, 3);
graph.addEdge(1, 2);
graph.addEdge(2, 4);
/*
* 0 <--> 1 <---> 2
* ↑ ↑
* | |
* | |
* ↓ ↓
* 3 4
*
* In this graph there are 4 bridges [1,0] , [2,1] , [4,2] , [3,1]
*
* Assuming that the graph is bi-directional and connected.
*
*/
Edge[] bridges = graph.findBridges();
System.out.println(bridges.length + " bridges found!");
for (Edge bridge : bridges) {
System.out.println(bridge.u + " --> " + bridge.v);
}
}
}