Skip to content

Commit 4177731

Browse files
author
duaraghav8@gmail
committed
Bridge-Finding in O(V+E) time
1 parent c503a35 commit 4177731

File tree

3 files changed

+116
-3
lines changed

3 files changed

+116
-3
lines changed
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
{
2-
"Bridges": "An edge in an undirected connected graph is a bridge iff removing it disconnects the graph. A naive solution to finding bridges in a graph is to:<br />1.Delete an edge E<br />2.Perform DFS Exploration to check if the Graph is still connected<br />3.Restore Edge E. E is a bridge only if DFS exploration determines that the graph is disconnected without E",
2+
"Bridges": "An edge in an undirected connected graph is a bridge iff removing it disconnects the graph. A naive solution to finding bridges in a graph is to:<br />1.Delete an edge E<br />2.Perform DFS Exploration to check if the Graph is still connected<br />3.Restore Edge E. E is a bridge only if DFS exploration determines that the graph is disconnected without E. An efficient solution also exists, which uses the idea that edge U-V (U is parent) is a bridge if no subtree rooted at V has a back edge to U or one of its ancestors.",
33
"Applications": [
44
"Finding vulnerabilities in Graphs and Electrical Circuits"
55
],
66
"Complexity": {
7-
"time": "worst O(|E|.(|V|+|E|))",
7+
"time": "worst Naive: O(|E|.(|V|+|E|)), Efficient: O(|V|+|E|)",
88
"space": "worst O(|V|.|E|)"
99
},
1010
"References": [
1111
"<a href='https://en.wikipedia.org/wiki/Bridge_(graph_theory)'>Wikipedia</a>"
1212
],
1313
"files": {
14-
"naive": "Find all the bridges in an Undirected Graph"
14+
"naive": "Find all the bridges in an Undirected Graph",
15+
"efficient": "Efficiently find all the bridges in an Undirected Graph"
1516
}
1617
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
NOTE: Code assumes NO parallel edges
3+
*/
4+
5+
var timer = 0, bridges = [], adj = []; //adj keeps track of the neighbors of each node
6+
7+
var util = function (u, visited, disc, low, parent) {
8+
logger._print ('');
9+
logger._print ('Visiting node ' + u);
10+
graphTracer._visit (u)._wait ();
11+
graphTracer._leave (u)._wait ();
12+
13+
visited [u] = true;
14+
disc [u] = low [u] = ++timer;
15+
16+
logger._print ('Nodes adjacent to ' + u + ' are: [ ' + adj [u] + ' ]');
17+
adj [u].forEach (function (v) {
18+
graphTracer._visit (v, u)._wait ();
19+
graphTracer._leave (v, u)._wait ();
20+
});
21+
22+
adj [u].forEach (function (v) {
23+
if (visited [v]) {
24+
logger._print (u + '\'s neighbor ' + v + ' has already been visited. Not visiting it.');
25+
}
26+
27+
if (!visited [v]) {
28+
logger._print (u + '\'s neighbor ' + v + ' has not been visited yet');
29+
logger._print ('Setting parent of ' + v + ' to ' + u + ' (parent [v] = u)');
30+
31+
parent [v] = u;
32+
33+
logger._print ('recursively calling util (' + v + ', [' + visited + '], [' + disc + '], [' + low + '], [' + parent + '])');
34+
util (v, visited, disc, low, parent);
35+
36+
logger._print ('--------------------------------------------------------------------');
37+
logger._print ('Returned from util (' + v + ', [' + visited + '], [' + disc + '], [' + low + '], [' + parent + '])');
38+
logger._print ('notice that the values of visited, disc, low and parent might have changed');
39+
40+
logger._print ('Setting low [' + u + '] to ' + Math.min (low [u], low [v]));
41+
low [u] = Math.min (low [u], low [v]);
42+
43+
if (low [v] > disc [u]) {
44+
logger._print ('low [v] > disc [u], v=' + v + ', u=' + u + ', (' + low [v] + ' > ' + low [u] + ')');
45+
logger._print (u + ' -> ' + v + ' is a bridge. Adding u->v to the set of bridges found');
46+
bridges.push ([u, v]);
47+
}
48+
}
49+
else if (v !== parent [u]) {
50+
logger._print (v + ' does not equal parent [' + u + '] (' + parent [u] + ')');
51+
logger._print ('Setting low [' + u + '] to ' + Math.min (low [u], disc [v]));
52+
low [u] = Math.min (low [u], disc [v]);
53+
}
54+
});
55+
};
56+
57+
(function findBridges (graph) {
58+
var visited = filledArray (graph.length, 0);
59+
var parent = filledArray (graph.length, -1);
60+
var disc = filledArray (graph.length, 0);
61+
var low = filledArray (graph.length, 0);
62+
63+
function filledArray (length, value) {
64+
return Array.apply (null, Array (length)).map (Number.prototype.valueOf, value);
65+
}
66+
67+
//PRECOMPUTATION: store every node's neighbor info in auxiliary array for efficient retrieval later
68+
(function computeAdj () {
69+
graph.forEach (function (config) {
70+
var temp = [];
71+
config.forEach (function (isEdge, i) {
72+
isEdge && temp.push (i);
73+
});
74+
adj.push (temp);
75+
});
76+
}) ();
77+
78+
for (var i = 0; i < visited.length; i++) { visited [i] = false; }
79+
80+
logger._print ('Initializing <b>visited</b>: ' + visited + ', <b>parent</b>: ' + parent + ', <b>disc</b>: ' + disc + ' <b>low</b>: ' + low);
81+
logger._print ('');
82+
logger._print ('Beginning efficient Bridge Finding');
83+
logger._print ('NOTE: call to util () follows pattern: util (nodeToVisit, visited, disc, low, parent). See code for clarity');
84+
logger._print ('');
85+
86+
logger._print ('Starting the main for loop (for each node)');
87+
for (var v = 0; v < graph.length; v++) {
88+
if (!visited [v]) {
89+
logger._print (v + ' has not been visited yet. Calling util (' + v + ', [' + visited + '], [' + disc + '], [' + low + '], [' + parent + ']) from the for loop');
90+
util (v, visited, disc, low, parent);
91+
logger._print ('Returned in for loop after util (' + v + ', [' + visited + '], [' + disc + '], [' + low + '], [' + parent + '])');
92+
}
93+
}
94+
}) (G);
95+
96+
logger._print ('There are ' + bridges.length + ' bridges in the Graph');
97+
for (var i = 0; i < bridges.length; i++) {
98+
logger._print (bridges [i] [0] + '-->' + bridges [i] [1]);
99+
}
100+
logger._print ('NOTE: All bridges are both ways (just like in the Naive Algorithm) because the Graph is undirected. So, edge A->B and B->A, both are bridges');
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var graphTracer = new UndirectedGraphTracer ();
2+
var logger = new LogTracer ();
3+
var G = [
4+
[0,1,0,0,0,0],
5+
[1,0,0,1,1,0],
6+
[0,0,0,1,0,0],
7+
[0,1,1,0,1,1],
8+
[0,1,0,1,0,0],
9+
[0,0,0,1,0,0]
10+
];
11+
12+
graphTracer._setData (G);

0 commit comments

Comments
 (0)