|
| 1 | + |
| 2 | +// A C++ program to find articulation points in an undirected graph |
| 3 | + |
| 4 | +#include<iostream> |
| 5 | +#include <list> |
| 6 | +#define NIL -1 |
| 7 | +using namespace std; |
| 8 | + |
| 9 | +// A class that represents an undirected graph |
| 10 | +class Graph |
| 11 | +{ |
| 12 | + int V; // No. of vertices |
| 13 | + list<int> *adj; // A dynamic array of adjacency lists |
| 14 | + void APUtil(int v, bool visited[], int disc[], int low[], |
| 15 | + int parent[], bool ap[]); |
| 16 | +public: |
| 17 | + Graph(int V); // Constructor |
| 18 | + void addEdge(int v, int w); // function to add an edge to graph |
| 19 | + void AP(); // prints articulation points |
| 20 | +}; |
| 21 | + |
| 22 | +Graph::Graph(int V) |
| 23 | +{ |
| 24 | + this->V = V; |
| 25 | + adj = new list<int>[V]; |
| 26 | +} |
| 27 | + |
| 28 | +void Graph::addEdge(int v, int w) |
| 29 | +{ |
| 30 | + adj[v].push_back(w); |
| 31 | + adj[w].push_back(v); // Note: the graph is undirected |
| 32 | +} |
| 33 | + |
| 34 | +// A recursive function that find articulation points using 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 | +// ap[] --> Store articulation points |
| 40 | +void Graph::APUtil(int u, bool visited[], int disc[], |
| 41 | + int low[], int parent[], bool ap[]) |
| 42 | +{ |
| 43 | + // A static variable is used for simplicity, we can avoid use of static |
| 44 | + // variable by passing a pointer. |
| 45 | + static int time = 0; |
| 46 | + |
| 47 | + // Count of children in DFS Tree |
| 48 | + int children = 0; |
| 49 | + |
| 50 | + // Mark the current node as visited |
| 51 | + visited[u] = true; |
| 52 | + |
| 53 | + // Initialize discovery time and low value |
| 54 | + disc[u] = low[u] = ++time; |
| 55 | + |
| 56 | + // Go through all vertices aadjacent to this |
| 57 | + list<int>::iterator i; |
| 58 | + for (i = adj[u].begin(); i != adj[u].end(); ++i) |
| 59 | + { |
| 60 | + int v = *i; // v is current adjacent of u |
| 61 | + |
| 62 | + // If v is not visited yet, then make it a child of u |
| 63 | + // in DFS tree and recur for it |
| 64 | + if (!visited[v]) |
| 65 | + { |
| 66 | + children++; |
| 67 | + parent[v] = u; |
| 68 | + APUtil(v, visited, disc, low, parent, ap); |
| 69 | + |
| 70 | + // Check if the subtree rooted with v has a connection to |
| 71 | + // one of the ancestors of u |
| 72 | + low[u] = min(low[u], low[v]); |
| 73 | + |
| 74 | + // u is an articulation point in following cases |
| 75 | + |
| 76 | + // (1) u is root of DFS tree and has two or more chilren. |
| 77 | + if (parent[u] == NIL && children > 1) |
| 78 | + ap[u] = true; |
| 79 | + |
| 80 | + // (2) If u is not root and low value of one of its child is more |
| 81 | + // than discovery value of u. |
| 82 | + if (parent[u] != NIL && low[v] >= disc[u]) |
| 83 | + ap[u] = true; |
| 84 | + } |
| 85 | + |
| 86 | + // Update low value of u for parent function calls. |
| 87 | + else if (v != parent[u]) |
| 88 | + low[u] = min(low[u], disc[v]); |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +// The function to do DFS traversal. It uses recursive function APUtil() |
| 93 | +void Graph::AP() |
| 94 | +{ |
| 95 | + // Mark all the vertices as not visited |
| 96 | + bool *visited = new bool[V]; |
| 97 | + int *disc = new int[V]; |
| 98 | + int *low = new int[V]; |
| 99 | + int *parent = new int[V]; |
| 100 | + bool *ap = new bool[V]; // To store articulation points |
| 101 | + |
| 102 | + // Initialize parent and visited, and ap(articulation point) arrays |
| 103 | + for (int i = 0; i < V; i++) |
| 104 | + { |
| 105 | + parent[i] = NIL; |
| 106 | + visited[i] = false; |
| 107 | + ap[i] = false; |
| 108 | + } |
| 109 | + |
| 110 | + // Call the recursive helper function to find articulation points |
| 111 | + // in DFS tree rooted with vertex 'i' |
| 112 | + for (int i = 0; i < V; i++) |
| 113 | + if (visited[i] == false) |
| 114 | + APUtil(i, visited, disc, low, parent, ap); |
| 115 | + |
| 116 | + // Now ap[] contains articulation points, print them |
| 117 | + for (int i = 0; i < V; i++) |
| 118 | + if (ap[i] == true) |
| 119 | + cout << i << " "; |
| 120 | +} |
| 121 | + |
| 122 | +int main() |
| 123 | +{ |
| 124 | + // Create graphs given in above diagrams |
| 125 | + cout << "\nArticulation points in first graph \n"; |
| 126 | + Graph g1(5); |
| 127 | + g1.addEdge(1, 0); |
| 128 | + g1.addEdge(0, 2); |
| 129 | + g1.addEdge(2, 1); |
| 130 | + g1.addEdge(0, 3); |
| 131 | + g1.addEdge(3, 4); |
| 132 | + g1.AP(); |
| 133 | + |
| 134 | + cout << "\nArticulation points in second graph \n"; |
| 135 | + Graph g2(4); |
| 136 | + g2.addEdge(0, 1); |
| 137 | + g2.addEdge(1, 2); |
| 138 | + g2.addEdge(2, 3); |
| 139 | + g2.AP(); |
| 140 | + |
| 141 | + cout << "\nArticulation points in third graph \n"; |
| 142 | + Graph g3(7); |
| 143 | + g3.addEdge(0, 1); |
| 144 | + g3.addEdge(1, 2); |
| 145 | + g3.addEdge(2, 0); |
| 146 | + g3.addEdge(1, 3); |
| 147 | + g3.addEdge(1, 4); |
| 148 | + g3.addEdge(1, 6); |
| 149 | + g3.addEdge(3, 5); |
| 150 | + g3.addEdge(4, 5); |
| 151 | + g3.AP(); |
| 152 | + |
| 153 | + return 0; |
| 154 | +} |
| 155 | +/* |
| 156 | +Explaination: |
| 157 | +
|
| 158 | +A O(V+E) algorithm to find all Articulation Points (APs) |
| 159 | +The idea is to use DFS (Depth First Search). In DFS, we follow vertices in tree form called DFS tree. In DFS tree, a vertex u is parent of another vertex v, if v is discovered by u (obviously v is an adjacent of u in graph). In DFS tree, a vertex u is articulation point if one of the following two conditions is true. |
| 160 | +1) u is root of DFS tree and it has at least two children. |
| 161 | +2) u is not root of DFS tree and it has a child v such that no vertex in subtree rooted with v has a back edge to one of the ancestors (in DFS tree) of u. |
| 162 | +
|
| 163 | +
|
| 164 | +*/ |
0 commit comments