1
+ #include < bits/stdc++.h>
2
+ using namespace std ;
3
+ #define IO_operations freopen (" input.txt" ," r" ,stdin); freopen(" output.txt" ," w" ,stdout);
4
+ unordered_map<int , vector<int >> adj;
5
+ vector<int > ap; // articulation point true, false
6
+ vector<int > disc; // discovery time of u
7
+ vector<int > low; // low node of 'u'
8
+ int time_discovered = 0 ;
9
+ // Articulation point
10
+
11
+ // graph ex:
12
+ // n = no of nodes
13
+ // m = no of edges
14
+ // n = 9, m = 9
15
+ // next m lines contains (u, v) which denotes edges btw u and v
16
+ // 9 9
17
+ // 1 3
18
+ // 1 2
19
+ // 2 3
20
+ // 2 4
21
+ // 4 5
22
+ // 4 6
23
+ // 2 7
24
+ // 7 8
25
+ // 8 9
26
+ // Condition for Articulation point
27
+ // Now we need to know if some vertex 𝑈
28
+ // is an articulation point. So, for that we will check the following conditions:
29
+
30
+ // If there is NO way to get to a node 𝑉
31
+ // with strictly smaller discovery time than the discovery time of 𝑈
32
+ // following the DFS traversal, then 𝑈
33
+ // is an articulation point. (it has to be strictly because if it is equal it means that 𝑈
34
+ // is the root of a cycle in the DFS traversal which means that 𝑈
35
+ // is still an articulation point).
36
+
37
+ // If 𝑈
38
+ // is the root of the DFS tree and it has at least 2 children subgraphs disconnected from each other, then 𝑈
39
+ // is an articulation point.
40
+
41
+
42
+ int dfsAP (int u, int p) {
43
+ int children = 0 ; // req for condition 2
44
+ disc[u] = low[u] = ++time_discovered; // add discovery time of node u and low[u] when first discovered
45
+ for (int &to: adj[u]) {
46
+ if (to == p) continue ; // we do not go back to the same path again or already discovered
47
+ if (!disc[to]) {
48
+ children++;
49
+ dfsAP (to, u);
50
+ if (disc[u] <= low[to]) { // means there is a no node which is ancestor of both u and to coz
51
+ ap[u] = 1 ; // u is a articulation point
52
+ } // if the condition do not hold then low[to] < disc[u] => low[to] is reachablve from some already discovered node
53
+ low[u] = min (low[u], low[to]); // low[v] might be an ancestor of u
54
+ } else {
55
+ // if already discovered
56
+ low[u] = min (low[u], disc[to]);
57
+ }
58
+ }
59
+ return children;
60
+ }
61
+
62
+ int main () {
63
+ #ifndef ONLINE_JUDGE
64
+ IO_operations;
65
+ #endif
66
+ int n, m; cin>>n>>m;
67
+ time_discovered = 0 ;
68
+ for (int i = 0 ; i < m; i++) {
69
+ int u, v; cin>>u>>v;
70
+ adj[u].push_back (v);
71
+ adj[v].push_back (u);
72
+ }
73
+
74
+ ap = low = disc = vector<int > (n + 1 , 0 );
75
+
76
+ for (int i = 1 ; i <= n; i++) {
77
+ if (!disc[i]) {
78
+ ap[i] = dfsAP (i, i) > 1 ; // condition 2 if i is root and atleast 2 subgraphs connected to it
79
+ }
80
+ }
81
+
82
+ cout<<" Articulation points are: " ;
83
+ for (int i = 1 ; i <= n; i++) if (ap[i]) cout<<i<<" " ;
84
+ return 0 ;
85
+ }
0 commit comments