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 <string>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>
#include <stack>

#define REP(i,k,n) for(int i=k;i<n;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define INF 1<<30
#define pb push_back
#define mp make_pair

using namespace std;
typedef long long ll;
typedef pair<int,int> P;

struct edge {
	int from,to;
	int cost;

	edge(int t,int c) : to(t),cost(c) {}
	edge(int f,int t,int c) : from(f),to(t),cost(c) {}

	bool operator<(const edge &e) const {
		return cost < e.cost;
	}
};

vector<edge> G[100005];
bool visited[100005];
int prenum[100005], par[100005], low[100005], timer;

void dfs(int cur, int prev) {
	prenum[cur] = low[cur] = timer;
	timer++;

	visited[cur] = true;
	int next;

	rep(i, G[cur].size()) {
		next = G[cur][i].to;

		if(!visited[next]) {
			par[next] = cur;
			dfs(next, cur);
			low[cur] = min(low[cur], low[next]);
		} else if(next != prev) {
			low[cur] = min(low[cur], prenum[next]);
		}
	} 
}

set<int> art_points(int n) {
	rep(i, n) visited[i] = false;
	timer = 1;

	dfs(0, -1);

	set<int> ap;
	int np = 0;
	REP(i, 1, n) {
		int p = par[i];
		if(p == 0) np++;
		else if(prenum[p] <= low[i]) ap.insert(p);
	}

	if(np > 1) ap.insert(0);
	return ap;
}
int main() {
	int n, m;
	cin >> n >> m;

	rep(i, m) {
		int s, t;
		cin >> s >> t;

		G[s].push_back(edge(t, 0));
		G[t].push_back(edge(s, 0));
	}

	set<int> st = art_points(n);
	set<int>::iterator ite;
	for(ite = st.begin(); ite != st.end(); ite++) {
		cout << *ite << endl;
	}

	return 0;
}