Given an undirected graph consisting of V vertices and E edges. The graph is represented as a 2D array edges[][], where each element edges[i] = [u, v] denotes an undirected edge between vertices u and v. Find all the articulation points in the graph. If no such points exist, return {-1}.
An articulation point is a vertex whose removal, along with all its connected edges, increases the number of connected components in the graph.
Note: The graph may be disconnected, meaning it can consist of multiple connected components.
[Naive Approach] - Using DFS - O(V × (V + E)) Time and O(V) Space
The idea is to traverse all the vertices and check whether it could be an articulation point or not. For that, remove the chosen vertex and call DFS (Depth First Search) on its neighbors. If DFS needs to be called more than once (i.e., multiple disconnected components are formed), then removing that vertex increases the number of components, so it is an articulation point.
C++
#include<iostream>#include<vector>usingnamespacestd;// Builds adjacency list from edge listvector<vector<int>>constructadj(intV,vector<vector<int>>&edges){vector<vector<int>>adj(V);for(autoit:edges){adj[it[0]].push_back(it[1]);adj[it[1]].push_back(it[0]);}returnadj;}// Standard DFS to mark all reachable nodesvoiddfs(intnode,vector<vector<int>>&adj,vector<bool>&visited){visited[node]=true;for(intneighbor:adj[node]){if(!visited[neighbor]){dfs(neighbor,adj,visited);}}}// Finds articulation points using naive DFS approachvector<int>articulationPoints(intV,vector<vector<int>>&adj){vector<int>res;// Try removing each node one by onefor(inti=0;i<V;++i){vector<bool>visited(V,false);visited[i]=true;// count DFS calls from i's neighborsintcomp=0;for(autoit:adj[i]){// early stop if already more than 1 componentif(comp>1)break;if(!visited[it]){// explore connected partdfs(it,adj,visited);comp++;}}// if more than one component forms, it's an articulation pointif(comp>1)res.push_back(i);}if(res.empty())return{-1};returnres;}intmain(){intV=5;vector<vector<int>>edges={{0,1},{1,4},{2,3},{2,4},{3,4}};vector<vector<int>>adj=constructadj(V,edges);vector<int>ans=articulationPoints(V,adj);for(autoit:ans){cout<<it<<" ";}return0;}
Java
importjava.util.ArrayList;importjava.util.Arrays;classGFG{// Builds adjacency list from edge liststaticArrayList<ArrayList<Integer>>constructadj(intV,int[][]edges){ArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++){adj.add(newArrayList<>());}for(int[]edge:edges){adj.get(edge[0]).add(edge[1]);adj.get(edge[1]).add(edge[0]);}returnadj;}// Standard DFS to mark all reachable nodesstaticvoiddfs(intnode,ArrayList<ArrayList<Integer>>adj,boolean[]visited){visited[node]=true;for(intneighbor:adj.get(node)){if(!visited[neighbor]){dfs(neighbor,adj,visited);}}}// Finds articulation points using naive DFS approachstaticArrayList<Integer>articulationPoints(intV,ArrayList<ArrayList<Integer>>adj){ArrayList<Integer>res=newArrayList<>();// Try removing each node one by onefor(inti=0;i<V;++i){boolean[]visited=newboolean[V];visited[i]=true;// count DFS calls from i's neighborsintcomp=0;for(intit:adj.get(i)){// early stop if already more than 1 componentif(comp>1)break;if(!visited[it]){// explore connected partdfs(it,adj,visited);comp++;}}// if more than one component forms, it's an articulation pointif(comp>1)res.add(i);}if(res.isEmpty())returnnewArrayList<>(Arrays.asList(-1));returnres;}publicstaticvoidmain(String[]args){intV=5;int[][]edges={{0,1},{1,4},{2,3},{2,4},{3,4}};ArrayList<ArrayList<Integer>>adj=constructadj(V,edges);ArrayList<Integer>ans=articulationPoints(V,adj);for(intit:ans){System.out.print(it+" ");}}}
Python
defconstructadj(V,edges):# Builds adjacency list from edge listadj=[[]for_inrange(V)]foru,vinedges:adj[u].append(v)adj[v].append(u)returnadj# Standard DFS to mark all reachable nodesdefdfs(node,adj,visited):# Standard DFS to mark all reachable nodesvisited[node]=Trueforneighborinadj[node]:ifnotvisited[neighbor]:dfs(neighbor,adj,visited)defarticulationPoints(V,adj):res=[]# Try removing each node one by oneforiinrange(V):visited=[False]*Vvisited[i]=True# count DFS calls from i's neighborscomp=0foritinadj[i]:ifcomp>1:breakifnotvisited[it]:# explore connected partdfs(it,adj,visited)comp+=1# if more than one component forms, it's an articulation pointifcomp>1:res.append(i)ifnotres:return[-1]returnresif__name__=="__main__":V=5edges=[[0,1],[1,4],[2,3],[2,4],[3,4]]# Finds articulation points using naive DFS approachadj=constructadj(V,edges)ans=articulationPoints(V,adj)foritinans:print(it,end=" ")
C#
usingSystem;usingSystem.Collections.Generic;classGFG{// Builds adjacency list from edge liststaticList<List<int>>constructAdj(intV,int[,]edges){List<List<int>>adj=newList<List<int>>();for(inti=0;i<V;i++){adj.Add(newList<int>());}intE=edges.GetLength(0);for(inti=0;i<E;i++){intu=edges[i,0];intv=edges[i,1];adj[u].Add(v);adj[v].Add(u);}returnadj;}// Standard DFS to mark all reachable nodesstaticvoidDFS(intnode,List<List<int>>adj,bool[]visited){visited[node]=true;foreach(intneighborinadj[node]){if(!visited[neighbor]){DFS(neighbor,adj,visited);}}}// Finds articulation points using naive DFS approachstaticList<int>articulationPoints(intV,List<List<int>>adj){List<int>res=newList<int>();// Try removing each node one by onefor(inti=0;i<V;++i){bool[]visited=newbool[V];visited[i]=true;// count DFS calls from i's neighborsintcomp=0;foreach(intitinadj[i]){// early stop if already more than 1 componentif(comp>1)break;if(!visited[it]){// explore connected partDFS(it,adj,visited);comp++;}}// if more than one component forms, it's an articulation pointif(comp>1)res.Add(i);}if(res.Count==0)returnnewList<int>{-1};returnres;}publicstaticvoidMain(string[]args){intV=5;int[,]edges=newint[,]{{0,1},{1,4},{2,3},{2,4},{3,4}};List<List<int>>adj=constructAdj(V,edges);List<int>ans=articulationPoints(V,adj);foreach(intitinans){Console.Write(it+" ");}}}
JavaScript
// Builds adjacency list from edge listfunctionconstructadj(V,edges){letadj=Array.from({length:V},()=>[]);for(let[u,v]ofedges){adj[u].push(v);adj[v].push(u);}returnadj;}// Standard DFS to mark all reachable nodesfunctiondfs(node,adj,visited){visited[node]=true;for(letneighborofadj[node]){if(!visited[neighbor]){dfs(neighbor,adj,visited);}}}// Finds articulation points using naive DFS approachfunctionarticulationPoints(V,adj){constres=[];// Try removing each node one by onefor(leti=0;i<V;++i){letvisited=Array(V).fill(false);visited[i]=true;// count DFS calls from i's neighborsletcomp=0;for(letitofadj[i]){// early stop if already more than 1 componentif(comp>1)break;if(!visited[it]){// explore connected partdfs(it,adj,visited);comp++;}}// if more than one component forms, it's an articulation pointif(comp>1)res.push(i);}if(res.length===0)return[-1];returnres;}// Driver Code constV=5;constedges=[[0,1],[1,4],[2,3],[2,4],[3,4]];constadj=constructadj(V,edges);constans=articulationPoints(V,adj);console.log(ans.join(" "));
Output
1 4
[Better Approach] - Using Tarjan's Algorithm - O(V + E) Time and O(V) Space
The idea is to use DFS to track how each node connects to its ancestors using discovery time and low values. Here, discovery time records when a node is first visited, and the low value represents the earliest (smallest) discovery time reachable from that node, including via back edges. For every node, we try to determine whether its subtree has an alternative path to reach an ancestor. If such a path does not exist for a child subtree, then the current node becomes a critical connection point, and removing it would disconnect that subtree from the rest of the graph. By propagating these low values during DFS, we can efficiently identify all nodes whose removal increases the number of connected components, i.e., the articulation points.
Let's understand with an example:
For the vertex 3 (which is not the root), vertex 4 is the child of vertex 3. No vertex in the subtree rooted at vertex 4 has a back edge to one of ancestors of vertex 3. Thus on removal of vertex 3 and its associated edges the graph will get disconnected or the number of components in the graph will increase as the subtree rooted at vertex 4 will form a separate component. Hence vertex 3 is an articulation point.
Now consider the following graph:
Again the vertex 4 is the child of vertex 3. For the subtree rooted at vertex 4, vertex 7 in this subtree has a back edge to one of the ancestors of vertex 3 (which is vertex 1). Thus this subtree will not get disconnected on the removal of vertex 3 because of this back edge. Since there is no child v of vertex 3, such that subtree rooted at vertex v does not have a back edge to one of the ancestors of vertex 3. Hence vertex 3 is not an articulation point in this case.
Step by Step implementation:
Maintain these arrays and integers and perform a DFS traversal.
disc[]: Discovery time of each vertex during DFS.
low[]: The lowest discovery time reachable from the subtree rooted at that vertex (via tree or back edges).
parent: To keep track of each node’s parent in the DFS tree.
visited[]: To mark visited nodes.
Root Node Case:
For the root node of DFS (i.e., parent[u] == -1), check how many child DFS calls it makes.
If the root has two or more children, it is an articulation point
For any non-root node u, check all its adjacent nodes:
If v is an unvisited child, recur for v, and after returning update low[u] = min(low[u], low[v]) .
If low[v] >= disc[u], then u is an articulation point because v and its subtree cannot reach any ancestor of u, so removing u would disconnect v.
Back Edge Case
If v is already visited and is not the parent of u then It’s a back edge. Update low[u] = min(low[u], disc[v])
This helps bubble up the lowest reachable ancestor through a back edge.
After DFS traversal completes, all nodes marked as articulation points are stored in result array.
C++
#include<iostream>#include<vector>usingnamespacestd;vector<vector<int>>constructAdj(intV,vector<vector<int>>&edges){vector<vector<int>>adj(V);for(auto&edge:edges){adj[edge[0]].push_back(edge[1]);adj[edge[1]].push_back(edge[0]);}returnadj;}// Helper function to perform DFS and find articulation points// using Tarjan's algorithm.voidfindPoints(vector<vector<int>>&adj,intu,vector<int>&visited,vector<int>&disc,vector<int>&low,int&time,intparent,vector<int>&isAP){// Mark vertex u as visited and assign discovery// time and low valuevisited[u]=1;disc[u]=low[u]=++time;intchildren=0;// Process all adjacent vertices of ufor(intv:adj[u]){// If v is not visited, then recursively visit itif(!visited[v]){children++;findPoints(adj,v,visited,disc,low,time,u,isAP);// Check if the subtree rooted at v has a // connection to one of the ancestors of ulow[u]=min(low[u],low[v]);// If u is not a root and low[v] is greater than or equal to disc[u],// then u is an articulation pointif(parent!=-1&&low[v]>=disc[u]){isAP[u]=1;}}// Update low value of u for back edgeelseif(v!=parent){low[u]=min(low[u],disc[v]);}}// If u is root of DFS tree and has more than // one child, it is an articulation pointif(parent==-1&&children>1){isAP[u]=1;}}// Main function to find articulation points in the graphvector<int>articulationPoints(intV,vector<vector<int>>&adj){vector<int>disc(V,0),low(V,0),visited(V,0),isAP(V,0);inttime=0;// Run DFS from each vertex if not// already visited (to handle disconnected graphs)for(intu=0;u<V;u++){if(!visited[u]){findPoints(adj,u,visited,disc,low,time,-1,isAP);}}// Collect all vertices that are articulation pointsvector<int>result;for(intu=0;u<V;u++){if(isAP[u]){result.push_back(u);}}// If no articulation points are found, return vector containing -1returnresult.empty()?vector<int>{-1}:result;}intmain(){intV=5;vector<vector<int>>edges={{0,1},{1,4},{2,3},{2,4},{3,4}};vector<vector<int>>adj=constructAdj(V,edges);vector<int>ans=articulationPoints(V,adj);for(intu:ans){cout<<u<<" ";}cout<<endl;return0;}
Java
importjava.util.ArrayList;classGFG{staticArrayList<ArrayList<Integer>>constructAdj(intV,int[][]edges){ArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());for(int[]edge:edges){adj.get(edge[0]).add(edge[1]);adj.get(edge[1]).add(edge[0]);}returnadj;}// Helper function to perform DFS and find articulation points// using Tarjan's algorithm.staticvoidfindPoints(ArrayList<ArrayList<Integer>>adj,intu,int[]visited,int[]disc,int[]low,int[]time,intparent,int[]isAP){// Mark vertex u as visited and assign discovery// time and low valuevisited[u]=1;disc[u]=low[u]=++time[0];intchildren=0;// Process all adjacent vertices of ufor(intv:adj.get(u)){// If v is not visited, then recursively visit itif(visited[v]==0){children++;findPoints(adj,v,visited,disc,low,time,u,isAP);// Check if the subtree rooted at v has a // connection to one of the ancestors of ulow[u]=Math.min(low[u],low[v]);// If u is not a root and low[v] is greater // than or equal to disc[u],// then u is an articulation pointif(parent!=-1&&low[v]>=disc[u]){isAP[u]=1;}}// Update low value of u for back edgeelseif(v!=parent){low[u]=Math.min(low[u],disc[v]);}}// If u is root of DFS tree and has more than // one child, it is an articulation pointif(parent==-1&&children>1){isAP[u]=1;}}// Main function to find articulation points in the graphstaticArrayList<Integer>articulationPoints(intV,ArrayList<ArrayList<Integer>>adj){int[]disc=newint[V],low=newint[V],visited=newint[V],isAP=newint[V];int[]time={0};// Run DFS from each vertex if not// already visited (to handle disconnected graphs)for(intu=0;u<V;u++){if(visited[u]==0){findPoints(adj,u,visited,disc,low,time,-1,isAP);}}// Collect all vertices that are articulation pointsArrayList<Integer>result=newArrayList<>();for(intu=0;u<V;u++){if(isAP[u]==1){result.add(u);}}// If no articulation points are found, return list containing -1if(result.isEmpty())result.add(-1);returnresult;}publicstaticvoidmain(String[]args){intV=5;int[][]edges={{0,1},{1,4},{2,3},{2,4},{3,4}};ArrayList<ArrayList<Integer>>adj=constructAdj(V,edges);ArrayList<Integer>ans=articulationPoints(V,adj);for(intu:ans){System.out.print(u+" ");}System.out.println();}}
Python
defconstructAdj(V,edges):adj=[[]for_inrange(V)]foredgeinedges:adj[edge[0]].append(edge[1])adj[edge[1]].append(edge[0])returnadj# Helper function to perform DFS and find articulation points# using Tarjan's algorithm.deffindPoints(adj,u,visited,disc,low,time,parent,isAP):# Mark vertex u as visited and assign discovery# time and low valuevisited[u]=1time[0]+=1disc[u]=low[u]=time[0]children=0# Process all adjacent vertices of uforvinadj[u]:# If v is not visited, then recursively visit itifnotvisited[v]:children+=1findPoints(adj,v,visited,disc,low,time,u,isAP)# Check if the subtree rooted at v has a # connection to one of the ancestors of ulow[u]=min(low[u],low[v])# If u is not a root and low[v] is greater than or equal to disc[u],# then u is an articulation pointifparent!=-1andlow[v]>=disc[u]:isAP[u]=1# Update low value of u for back edgeelifv!=parent:low[u]=min(low[u],disc[v])# If u is root of DFS tree and has more than # one child, it is an articulation pointifparent==-1andchildren>1:isAP[u]=1# Main function to find articulation points in the graphdefarticulationPoints(V,adj):disc=[0]*Vlow=[0]*Vvisited=[0]*VisAP=[0]*Vtime=[0]# Run DFS from each vertex if not# already visited (to handle disconnected graphs)foruinrange(V):ifnotvisited[u]:findPoints(adj,u,visited,disc,low,time,-1,isAP)# Collect all vertices that are articulation pointsresult=[uforuinrange(V)ifisAP[u]]# If no articulation points are found, return list containing -1returnresultifresultelse[-1]if__name__=="__main__":V=5edges=[[0,1],[1,4],[2,3],[2,4],[3,4]]adj=constructAdj(V,edges)ans=articulationPoints(V,adj)foruinans:print(u,end=' ')print()
C#
usingSystem;usingSystem.Collections.Generic;classGFG{staticList<List<int>>constructAdj(intV,int[,]edges){List<List<int>>adj=newList<List<int>>();for(inti=0;i<V;i++){adj.Add(newList<int>());}intM=edges.GetLength(0);for(inti=0;i<M;i++){intu=edges[i,0];intv=edges[i,1];adj[u].Add(v);adj[v].Add(u);}returnadj;}// Helper function to perform DFS and find articulation points// using Tarjan's algorithm.staticvoidfindPoints(List<List<int>>adj,intu,List<int>visited,List<int>disc,List<int>low,refinttime,intparent,List<int>isAP){// Mark vertex u as visited and assign discovery// time and low valuevisited[u]=1;disc[u]=low[u]=++time;intchildren=0;// Process all adjacent vertices of uforeach(intvinadj[u]){// If v is not visited, then recursively visit itif(visited[v]==0){children++;findPoints(adj,v,visited,disc,low,reftime,u,isAP);// Check if the subtree rooted at v has a // connection to one of the ancestors of ulow[u]=Math.Min(low[u],low[v]);// If u is not a root and low[v] is greater // than or equal to disc[u],// then u is an articulation pointif(parent!=-1&&low[v]>=disc[u]){isAP[u]=1;}}// Update low value of u for back edgeelseif(v!=parent){low[u]=Math.Min(low[u],disc[v]);}}// If u is root of DFS tree and has more than // one child, it is an articulation pointif(parent==-1&&children>1){isAP[u]=1;}}// Main function to find articulation points in the graphstaticList<int>articulationPoints(intV,List<List<int>>adj){List<int>disc=newList<int>(newint[V]);List<int>low=newList<int>(newint[V]);List<int>visited=newList<int>(newint[V]);List<int>isAP=newList<int>(newint[V]);inttime=0;// Run DFS from each vertex if not// already visited (to handle disconnected graphs)for(intu=0;u<V;u++){if(visited[u]==0){findPoints(adj,u,visited,disc,low,reftime,-1,isAP);}}// Collect all vertices that are articulation pointsList<int>result=newList<int>();for(intu=0;u<V;u++){if(isAP[u]==1){result.Add(u);}}// If no articulation points are found, return list containing -1returnresult.Count==0?newList<int>{-1}:result;}staticvoidMain(){intV=5;int[,]edges={{0,1},{1,4},{2,3},{2,4},{3,4}};List<List<int>>adj=constructAdj(V,edges);List<int>ans=articulationPoints(V,adj);foreach(intuinans){Console.Write(u+" ");}Console.WriteLine();}}
JavaScript
// Build adjacency list from edge listfunctionconstructAdj(V,edges){constadj=Array.from({length:V},()=>[]);for(leti=0;i<edges.length;i++){const[u,v]=edges[i];adj[u].push(v);adj[v].push(u);}returnadj;}// Helper function to perform DFS and find articulation points// using Tarjan's algorithm.functionfindPoints(adj,u,visited,disc,low,timeRef,parent,isAP){// Mark vertex u as visited and assign discovery// time and low valuevisited[u]=1;disc[u]=low[u]=++timeRef.value;letchildren=0;// Process all adjacent vertices of ufor(letvofadj[u]){// If v is not visited, then recursively visit itif(!visited[v]){children++;findPoints(adj,v,visited,disc,low,timeRef,u,isAP);// Check if the subtree rooted at v has a // connection to one of the ancestors of ulow[u]=Math.min(low[u],low[v]);// If u is not a root and low[v] is greater // than or equal to disc[u],// then u is an articulation pointif(parent!==-1&&low[v]>=disc[u]){isAP[u]=1;}}// Update low value of u for back edgeelseif(v!==parent){low[u]=Math.min(low[u],disc[v]);}}// If u is root of DFS tree and has more than // one child, it is an articulation pointif(parent===-1&&children>1){isAP[u]=1;}}// Main function to find articulation points in the graphfunctionarticulationPoints(V,adj){constdisc=Array(V).fill(0);constlow=Array(V).fill(0);constvisited=Array(V).fill(0);constisAP=Array(V).fill(0);consttimeRef={value:0};// Run DFS from each vertex if not// already visited (to handle disconnected graphs)for(letu=0;u<V;u++){if(!visited[u]){findPoints(adj,u,visited,disc,low,timeRef,-1,isAP);}}// Collect all vertices that are articulation pointsconstresult=[];for(letu=0;u<V;u++){if(isAP[u]){result.push(u);}}// If no articulation points are found, return array containing -1returnresult.length===0?[-1]:result;}// Driver CodeconstV=5;constedges=[[0,1],[1,4],[2,3],[2,4],[3,4]];constadj=constructAdj(V,edges);constans=articulationPoints(V,adj);console.log(ans.join(' '));
Output
1 4
[Expected Approach] - Using Tarjan’s Algorithm (Iterative Method) - O(V + E) Time and O(V) Space
We can use Tarjan’s algorithm with an explicit stack to manage the traversal state instead of relying on the system’s call stack. The logic remains the same that we maintain disc, low, parent, and childrenCount but we manually control how nodes are processed.
For each node, we store its current state, including which neighbor to visit next and whether the node is in the entering or exiting phase.
With this approach, we preserve the core idea of Tarjan’s algorithm while making it more suitable for large or deep graphs.
C++
#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;voidtarjan(intstart,vector<vector<int>>&adj,vector<bool>&visited,vector<int>&disc,vector<int>&low,vector<int>&parent,vector<int>&childrenCount,vector<bool>&ap){// Stack stores {node, neighborIndex, state}intn=adj.size();vector<array<int,3>>stack(n*2);inttop=0,time=0;stack[top++]={start,0,0};while(top>0){intu=stack[top-1][0],idx=stack[top-1][1],state=stack[top-1][2];top--;if(state==0){// First visit: mark discovery and lowif(!visited[u]){visited[u]=true;disc[u]=low[u]=++time;}// Process neighborsif(idx<(int)adj[u].size()){intv=adj[u][idx];// Push current node with next neighborstack[top++]={u,idx+1,0};// Visit childif(!visited[v]){parent[v]=u;childrenCount[u]++;stack[top++]={v,0,0};}// Back edgeelseif(v!=parent[u]){low[u]=min(low[u],disc[v]);}}// Finished neighbors, push exit stateelse{stack[top++]={u,0,1};}}else{// Update parent low and mark articulationif(top>0){intp=stack[top-1][0];low[p]=min(low[p],low[u]);if(parent[p]!=-1&&low[u]>=disc[p])ap[p]=true;}// Root articulation checkelseif(childrenCount[start]>1){ap[start]=true;}}}}// Main function to find articulation pointsvector<int>articulationPoints(intV,vector<vector<int>>&adj){// Initialize arraysvector<int>disc(V,0),low(V,0),parent(V,-1),childrenCount(V,0);vector<bool>visited(V,false),ap(V,false);// Run iterative DFS for each componentfor(inti=0;i<V;i++){if(!visited[i])tarjan(i,adj,visited,disc,low,parent,childrenCount,ap);}// Collect articulation pointsvector<int>result;for(inti=0;i<V;i++)if(ap[i])result.push_back(i);if(result.empty())result.push_back(-1);returnresult;}intmain(){intV=5;intedges[5][2]={{0,1},{1,4},{2,3},{2,4},{3,4}};// Build adjacency listvector<vector<int>>adj(V);for(auto&e:edges){adj[e[0]].push_back(e[1]);adj[e[1]].push_back(e[0]);}vector<int>ans=articulationPoints(V,adj);for(intx:ans)cout<<x<<" ";cout<<"\n";}
Java
importjava.util.ArrayList;classGFG{staticArrayList<Integer>articulationPoints(intV,ArrayList<ArrayList<Integer>>adj){int[]disc=newint[V],low=newint[V],parent=newint[V],childrenCount=newint[V];boolean[]visited=newboolean[V],ap=newboolean[V];for(inti=0;i<V;i++)parent[i]=-1;// Run iterative DFS for each componentfor(inti=0;i<V;i++){if(!visited[i])tarjan(i,adj,visited,disc,low,parent,childrenCount,ap);}// Collect articulation pointsArrayList<Integer>result=newArrayList<>();for(inti=0;i<V;i++)if(ap[i])result.add(i);if(result.isEmpty())result.add(-1);returnresult;}privatestaticvoidtarjan(intstart,ArrayList<ArrayList<Integer>>adj,boolean[]visited,int[]disc,int[]low,int[]parent,int[]childrenCount,boolean[]ap){// Stack stores {node, neighborIndex, state}int[][]stack=newint[visited.length*2][3];inttop=0,time=0;stack[top++]=newint[]{start,0,0};while(top>0){intu=stack[top-1][0],idx=stack[top-1][1],state=stack[top-1][2];top--;if(state==0){// First visit: mark discovery and lowif(!visited[u]){visited[u]=true;disc[u]=low[u]=++time;}// Process neighborsif(idx<adj.get(u).size()){intv=adj.get(u).get(idx);// Push current node with next neighborstack[top++]=newint[]{u,idx+1,0};// Visit childif(!visited[v]){parent[v]=u;childrenCount[u]++;stack[top++]=newint[]{v,0,0};}// Back edgeelseif(v!=parent[u]){low[u]=Math.min(low[u],disc[v]);}}// Finished neighbors, push exit stateelse{stack[top++]=newint[]{u,0,1};}}// Exiting nodeelse{// Update parent low and mark articulationif(top>0){intp=stack[top-1][0];low[p]=Math.min(low[p],low[u]);if(parent[p]!=-1&&low[u]>=disc[p])ap[p]=true;}// Root articulation checkelseif(childrenCount[start]>1){ap[start]=true;}}}}publicstaticvoidmain(String[]args){intV=5;// Build adjacency listArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());int[][]edges={{0,1},{1,4},{2,3},{2,4},{3,4}};for(int[]e:edges){adj.get(e[0]).add(e[1]);adj.get(e[1]).add(e[0]);}ArrayList<Integer>ans=articulationPoints(V,adj);for(intx:ans){System.out.print(x+" ");}}}
Python
defarticulation_points(V,adj):# discovery timesdisc=[0]*V# low valueslow=[0]*Vparent=[-1]*Vchildren_count=[0]*Vvisited=[False]*Vap=[False]*V# Run iterative DFS for each componentforiinrange(V):ifnotvisited[i]:tarjan(i,adj,visited,disc,low,parent,children_count,ap)# Collect articulation pointsresult=[iforiinrange(V)ifap[i]]returnresultifresultelse[-1]deftarjan(start,adj,visited,disc,low,parent,children_count,ap):# Stack stores {node, neighborIndex, state}# state 0 = entering, 1 = exitingstack=[[start,0,0]]time=0whilestack:u,idx,state=stack.pop()ifstate==0:# First visit: mark discovery and lowifnotvisited[u]:visited[u]=Truetime+=1disc[u]=low[u]=time# Process neighborsifidx<len(adj[u]):v=adj[u][idx]# Push current node with next neighborstack.append([u,idx+1,0])# Visit childifnotvisited[v]:parent[v]=uchildren_count[u]+=1stack.append([v,0,0])# Back edgeelifv!=parent[u]:low[u]=min(low[u],disc[v])else:# Finished neighbors, push exit statestack.append([u,0,1])else:# Update parent low and mark articulationifstack:p=stack[-1][0]low[p]=min(low[p],low[u])ifparent[p]!=-1andlow[u]>=disc[p]:ap[p]=True# Root articulation checkelse:ifchildren_count[start]>1:ap[start]=Trueif__name__=="__main__":V=5# Build adjacency listadj=[[]for_inrange(V)]edges=[(0,1),(1,4),(2,3),(2,4),(3,4)]foru,vinedges:adj[u].append(v)adj[v].append(u)print(*articulation_points(V,adj))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{privatevoidtarjan(intstart,List<List<int>>adj,bool[]visited,int[]disc,int[]low,int[]parent,int[]childrenCount,bool[]ap){// Stack stores {node, neighborIndex, state}intn=adj.Count;varstack=newList<int[]>(n*2);inttime=0;stack.Add(newint[]{start,0,0});while(stack.Count>0){vartopElem=stack[stack.Count-1];stack.RemoveAt(stack.Count-1);intu=topElem[0],idx=topElem[1],state=topElem[2];if(state==0){// First visit: mark discovery and lowif(!visited[u]){visited[u]=true;disc[u]=low[u]=++time;}// Process neighborsif(idx<adj[u].Count){intv=adj[u][idx];// Push current node with next neighborstack.Add(newint[]{u,idx+1,0});// Visit childif(!visited[v]){parent[v]=u;childrenCount[u]++;stack.Add(newint[]{v,0,0});}// Back edgeelseif(v!=parent[u]){low[u]=Math.Min(low[u],disc[v]);}}// Finished neighbors, push exit stateelse{stack.Add(newint[]{u,0,1});}}else{// Update parent low and mark articulationif(stack.Count>0){intp=stack[stack.Count-1][0];low[p]=Math.Min(low[p],low[u]);if(parent[p]!=-1&&low[u]>=disc[p])ap[p]=true;}// Root articulation checkelseif(childrenCount[start]>1){ap[start]=true;}}}}// Main function to find articulation pointspublicList<int>articulationPoints(intV,List<List<int>>adj){// Initialize arraysint[]disc=newint[V],low=newint[V],parent=newint[V],childrenCount=newint[V];bool[]visited=newbool[V],ap=newbool[V];for(inti=0;i<V;i++)parent[i]=-1;// Run iterative DFS for each componentfor(inti=0;i<V;i++){if(!visited[i]){tarjan(i,adj,visited,disc,low,parent,childrenCount,ap);}}// Collect articulation pointsvarresult=newList<int>();for(inti=0;i<V;i++)if(ap[i])result.Add(i);if(result.Count==0)result.Add(-1);returnresult;}staticvoidMain(){intV=5;// Build adjacency listvaradj=newList<List<int>>();for(inti=0;i<V;i++)adj.Add(newList<int>());int[][]edges=newint[][]{newint[]{0,1},newint[]{1,4},newint[]{2,3},newint[]{2,4},newint[]{3,4}};foreach(vareinedges){adj[e[0]].Add(e[1]);adj[e[1]].Add(e[0]);}varsol=newGFG();varans=sol.articulationPoints(V,adj);Console.WriteLine(string.Join(" ",ans));}}
JavaScript
functionarticulationPoints(V,adj){// Initialize arraysconstdisc=Array(V).fill(0);constlow=Array(V).fill(0);constparent=Array(V).fill(-1);constchildrenCount=Array(V).fill(0);constvisited=Array(V).fill(false);constap=Array(V).fill(false);// Run iterative DFS for each componentfor(leti=0;i<V;i++){if(!visited[i]){tarjan(i,adj,visited,disc,low,parent,childrenCount,ap);}}// Collect articulation pointsconstresult=[];for(leti=0;i<V;i++)if(ap[i])result.push(i);if(result.length===0)result.push(-1);returnresult;}functiontarjan(start,adj,visited,disc,low,parent,childrenCount,ap){// Stack stores {node, neighborIndex, state}conststack=[];lettime=0;stack.push([start,0,0]);// state 0 = entering, 1 = exitingwhile(stack.length>0){const[u,idx,state]=stack.pop();if(state===0){// First visit: mark discovery and lowif(!visited[u]){visited[u]=true;disc[u]=low[u]=++time;}// Process neighborsif(idx<adj[u].length){constv=adj[u][idx];// Push current node with next neighborstack.push([u,idx+1,0]);// Visit childif(!visited[v]){parent[v]=u;childrenCount[u]++;stack.push([v,0,0]);}// Back edgeelseif(v!==parent[u]){low[u]=Math.min(low[u],disc[v]);}}// Finished neighbors, push exit stateelse{stack.push([u,0,1]);}}// Exiting nodeelse{// Update parent low and mark articulationif(stack.length>0){constp=stack[stack.length-1][0];low[p]=Math.min(low[p],low[u]);if(parent[p]!==-1&&low[u]>=disc[p])ap[p]=true;}// Root articulation checkelseif(childrenCount[start]>1){ap[start]=true;}}}}// Driver codeconstV=5;// Build adjacency listconstadj=Array.from({length:V},()=>[]);constedges=[[0,1],[1,4],[2,3],[2,4],[3,4]];for(const[u,v]ofedges){adj[u].push(v);adj[v].push(u);}console.log(articulationPoints(V,adj).join(" "));