Problem:
Articulation Points

Find articulation points of a given undirected graph G(V, E).

A vertex in an undirected graph is an articulation point (or cut vertex) iff removing it disconnects the graph.

Input

|V| |E|
s0 t0
s1 t1
:
s|E|-1 t|E|-1

, where |V| is the number of vertices and |E| is the number of edges in the graph. The graph vertices are named with the numbers 0, 1,..., |V|-1 respectively.

si and ti represent source and target verticess of i-th edge (undirected).

Output

A list of articulation points of the graph G ordered by name.

Constraints

1 ≤ |V| ≤ 100,000

0 ≤ |E| ≤ 100,000

The graph is connected

There are no parallel edges

There are no self-loops

Sample Input 1

4 4
0 1
0 2
1 2
2 3

Sample Output 1

2

Sample Input 2

5 4
0 1
1 2
2 3
3 4

Sample Output 2

1
2
3

Solution in C++ (judge verdict: Accepted)

#include<iostream>
#include<vector>
#include<set>
using namespace std;

#define MAX 100000

vector<int> G[MAX];
int N;
bool visited[MAX];
int prenum[MAX], parent[MAX], lowest[MAX], timer;

void dfs(int current, int prev){
    prenum[current] = lowest[current] = timer;
    timer++;

    visited[current] = true;

    int next;

    for(int i=0; i<G[current].size(); i++){
        next = G[current][i];
        if(!visited[next]){
            parent[next] = current;
            dfs(next, current);
            // ノード next の探索が終了した直後の処理
            lowest[current] = min(lowest[current], lowest[next]);
        }
        else if(next != prev){
            // エッジ current --> next が Back-edgeの場合の処理
            lowest[current] = min(lowest[current], prenum[next]);
        }
    }
}

void art_points(){
    for(int i=0; i<N; i++) visited[i] = false;
    timer = 1;
    dfs(0, -1); 
    
    set<int> ap;
    int np = 0;
    for(int i=1; i<N; i++){
        int p=parent[i];
        if(p==0) np++;
        else if(prenum[p] <= lowest[i]) ap.insert(p);
    }
    if(np > 1) ap.insert(0);
    for(set<int>::iterator it = ap.begin(); it != ap.end(); it++){
        cout << *it << endl;
    }
}

int main(int argc, char const *argv[])
{
    int m;
    cin >> N >> m;
    for(int i=0; i<m; i++){
        int s, t;
        cin >> s >> t;
        G[s].push_back(t);
        G[t].push_back(s);
    }
    art_points();

    return 0;
}