|
| 1 | + |
| 2 | +// A C++ program to find bridges in a given undirected graph |
| 3 | +#include<iostream> |
| 4 | +#include <list> |
| 5 | +#define NIL -1 |
| 6 | +using namespace std; |
| 7 | + |
| 8 | +// A class that represents an undirected graph |
| 9 | +class Graph |
| 10 | +{ |
| 11 | + int V; // No. of vertices |
| 12 | + list<int> *adj; // A dynamic array of adjacency lists |
| 13 | + void bridgeUtil(int v, bool visited[], int disc[], int low[], |
| 14 | + int parent[]); |
| 15 | +public: |
| 16 | + Graph(int V); // Constructor |
| 17 | + void addEdge(int v, int w); // to add an edge to graph |
| 18 | + void bridge(); // prints all bridges |
| 19 | +}; |
| 20 | + |
| 21 | +Graph::Graph(int V) |
| 22 | +{ |
| 23 | + this->V = V; |
| 24 | + adj = new list<int>[V]; |
| 25 | +} |
| 26 | + |
| 27 | +void Graph::addEdge(int v, int w) |
| 28 | +{ |
| 29 | + adj[v].push_back(w); |
| 30 | + adj[w].push_back(v); // Note: the graph is undirected |
| 31 | +} |
| 32 | + |
| 33 | +// A recursive function that finds and prints bridges using |
| 34 | +// DFS traversal |
| 35 | +// u --> The vertex to be visited next |
| 36 | +// visited[] --> keeps tract of visited vertices |
| 37 | +// disc[] --> Stores discovery times of visited vertices |
| 38 | +// parent[] --> Stores parent vertices in DFS tree |
| 39 | +void Graph::bridgeUtil(int u, bool visited[], int disc[], |
| 40 | + int low[], int parent[]) |
| 41 | +{ |
| 42 | + // A static variable is used for simplicity, we can |
| 43 | + // avoid use of static variable by passing a pointer. |
| 44 | + static int time = 0; |
| 45 | + |
| 46 | + // Mark the current node as visited |
| 47 | + visited[u] = true; |
| 48 | + |
| 49 | + // Initialize discovery time and low value |
| 50 | + disc[u] = low[u] = ++time; |
| 51 | + |
| 52 | + // Go through all vertices aadjacent to this |
| 53 | + list<int>::iterator i; |
| 54 | + for (i = adj[u].begin(); i != adj[u].end(); ++i) |
| 55 | + { |
| 56 | + int v = *i; // v is current adjacent of u |
| 57 | + |
| 58 | + // If v is not visited yet, then recur for it |
| 59 | + if (!visited[v]) |
| 60 | + { |
| 61 | + parent[v] = u; |
| 62 | + bridgeUtil(v, visited, disc, low, parent); |
| 63 | + |
| 64 | + // Check if the subtree rooted with v has a |
| 65 | + // connection to one of the ancestors of u |
| 66 | + low[u] = min(low[u], low[v]); |
| 67 | + |
| 68 | + // If the lowest vertex reachable from subtree |
| 69 | + // under v is below u in DFS tree, then u-v |
| 70 | + // is a bridge |
| 71 | + if (low[v] > disc[u]) |
| 72 | + cout << u <<" " << v << endl; |
| 73 | + } |
| 74 | + |
| 75 | + // Update low value of u for parent function calls. |
| 76 | + else if (v != parent[u]) |
| 77 | + low[u] = min(low[u], disc[v]); |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +// DFS based function to find all bridges. It uses recursive |
| 82 | +// function bridgeUtil() |
| 83 | +void Graph::bridge() |
| 84 | +{ |
| 85 | + // Mark all the vertices as not visited |
| 86 | + bool *visited = new bool[V]; |
| 87 | + int *disc = new int[V]; |
| 88 | + int *low = new int[V]; |
| 89 | + int *parent = new int[V]; |
| 90 | + |
| 91 | + // Initialize parent and visited arrays |
| 92 | + for (int i = 0; i < V; i++) |
| 93 | + { |
| 94 | + parent[i] = NIL; |
| 95 | + visited[i] = false; |
| 96 | + } |
| 97 | + |
| 98 | + // Call the recursive helper function to find Bridges |
| 99 | + // in DFS tree rooted with vertex 'i' |
| 100 | + for (int i = 0; i < V; i++) |
| 101 | + if (visited[i] == false) |
| 102 | + bridgeUtil(i, visited, disc, low, parent); |
| 103 | +} |
| 104 | + |
| 105 | +// Driver program to test above function |
| 106 | +int main() |
| 107 | +{ |
| 108 | + // Create graphs given in above diagrams |
| 109 | + cout << "\nBridges in first graph \n"; |
| 110 | + Graph g1(5); |
| 111 | + g1.addEdge(1, 0); |
| 112 | + g1.addEdge(0, 2); |
| 113 | + g1.addEdge(2, 1); |
| 114 | + g1.addEdge(0, 3); |
| 115 | + g1.addEdge(3, 4); |
| 116 | + g1.bridge(); |
| 117 | + |
| 118 | + cout << "\nBridges in second graph \n"; |
| 119 | + Graph g2(4); |
| 120 | + g2.addEdge(0, 1); |
| 121 | + g2.addEdge(1, 2); |
| 122 | + g2.addEdge(2, 3); |
| 123 | + g2.bridge(); |
| 124 | + |
| 125 | + cout << "\nBridges in third graph \n"; |
| 126 | + Graph g3(7); |
| 127 | + g3.addEdge(0, 1); |
| 128 | + g3.addEdge(1, 2); |
| 129 | + g3.addEdge(2, 0); |
| 130 | + g3.addEdge(1, 3); |
| 131 | + g3.addEdge(1, 4); |
| 132 | + g3.addEdge(1, 6); |
| 133 | + g3.addEdge(3, 5); |
| 134 | + g3.addEdge(4, 5); |
| 135 | + g3.bridge(); |
| 136 | + |
| 137 | + return 0; |
| 138 | +} |
| 139 | +/* |
| 140 | +A O(V+E) algorithm to find all Bridges |
| 141 | +The idea is similar to O(V+E) algorithm for Articulation Points. |
| 142 | + We do DFS traversal of the given graph. In DFS tree an edge (u, v) (u is parent of v in DFS tree) is bridge if there does not exist any other alternative to reach u or an ancestor of u from subtree rooted with v. |
| 143 | + the value low[v] indicates earliest visited vertex reachable from subtree rooted with v. |
| 144 | +The condition for an edge (u, v) to be a bridge is, “low[v] > disc[u]” |
| 145 | +
|
| 146 | +*/ |
0 commit comments