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++
//Driver Code Starts#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;}//Driver Code Ends// 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;}//Driver Code Startsintmain(){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;}//Driver Code Ends
Java
//Driver Code Startsimportjava.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;}//Driver Code Ends// 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;}//Driver Code Startspublicstaticvoidmain(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+" ");}}}//Driver Code Ends
Python
#Driver Code Startsdefconstructadj(V,edges):# Builds adjacency list from edge listadj=[[]for_inrange(V)]foru,vinedges:adj[u].append(v)adj[v].append(u)returnadj#Driver Code Ends# 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]returnres#Driver Code Startsif__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=" ")#Driver Code Ends
C#
//Driver Code StartsusingSystem;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;}//Driver Code Ends// 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;}//Driver Code StartspublicstaticvoidMain(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+" ");}}}//Driver Code Ends
JavaScript
//Driver Code Starts// 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;}//Driver Code Ends// 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 Starts// 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(" "));//Driver Code Ends
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++
//Driver Code Starts#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;}//Driver Code Ends// 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;}//Driver Code Startsintmain(){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;}//Driver Code Ends
Java
//Driver Code Startsimportjava.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;}//Driver Code Ends// 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;}//Driver Code Startspublicstaticvoidmain(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();}}//Driver Code Ends
Python
#Driver Code StartsdefconstructAdj(V,edges):adj=[[]for_inrange(V)]foredgeinedges:adj[edge[0]].append(edge[1])adj[edge[1]].append(edge[0])returnadj#Driver Code Ends# 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]#Driver Code Startsif__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()#Driver Code Ends
C#
//Driver Code StartsusingSystem;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;}//Driver Code Ends// 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;}//Driver Code StartsstaticvoidMain(){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();}}//Driver Code Ends
JavaScript
//Driver Code Starts// 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;}//Driver Code Ends// 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 Code Starts// 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(' '));//Driver Code Ends
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++
//Driver Code Starts#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;//Driver Code Endsvoidtarjan(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;}//Driver Code Startsintmain(){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<<"";}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;classGfG{//Driver Code EndsstaticArrayList<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;}}}}//Driver Code Startspublicstaticvoidmain(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+" ");}}}//Driver Code Ends
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]=True#Driver Code Startsif__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))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classSolution{//Driver Code Endsprivatevoidtarjan(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;}//Driver Code StartsstaticvoidMain(){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=newSolution();varans=sol.articulationPoints(V,adj);Console.WriteLine(string.Join(" ",ans));}}//Driver Code Ends
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 Code Starts// 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(" "));//Driver Code Ends