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)

using System;
using System.Collections.Generic;
using System.Linq;

namespace GRL3_A
{
    class Program
    {
        const int MAX = 100000;
        static List<int>[] G = Enumerable.Range(0, MAX).Select(n => new List<int>()).ToArray();
        static int N, timer = 1;
        static int[] prenum = new int[MAX], parent = new int[MAX], lowest = Enumerable.Repeat(int.MaxValue,MAX).ToArray();
        static bool[] visited = new bool[MAX];

        static void Main(string[] args)
        {
            var t = scan;
            N = t[0];
            int m = t[1];

            for (int i = 0; i < m; i++)
            {
                t = scan;
                G[t[0]].Add(t[1]);
                G[t[1]].Add(t[0]);
            }
            art_points();
        }
        static void art_points()
        {
            dfs(0, -1);
            var ap = new HashSet<int>();
            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.Add(p);

            }
            if (np > 1) ap.Add(0);
            var a = ap.OrderBy(s => s);
            foreach (var item in a)
            {
                Console.WriteLine(item);
            }
        }
        static void dfs(int current, int prev)
        {
            prenum[current] = timer;
            lowest[current] = timer;
            timer++;
            visited[current] = true;

            int next;

            for (int i = 0; i < G[current].Count; i++)
            {
                next = G[current][i];
                if (!visited[next])
                {
                    parent[next] = current;
                    dfs(next, current);
                    lowest[current] = Math.Min(lowest[current], lowest[next]);
                }
                else if (next != prev) lowest[current] = Math.Min(lowest[current], prenum[next]);
            }
        }
        static int[] scan { get { return Array.ConvertAll(Console.ReadLine().Split(), int.Parse); } }
    }
}