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.Linq;//リストの使用
using System.Collections.Generic;
using System.Text;//テキストの高速出力に必要
class Program
{
static string[] input = Console.ReadLine().Split(' ');//Splitで区切り文字を指定して複数個受け取る。
static int v = int.Parse(input[0]);
static int e = int.Parse(input[1]);
static List<int>[] nextList = new List<int>[v];
static bool[] checkedVertex = new bool[v];//頂点を確認済みか？
static int timer = 0;
static int[] prenum = new int[v];
static int[] lowest = new int[v];
static int[] parent = new int[v];
static List<int> answers = new List<int>();

	static void Main()
	{
    for(long i = 0; i < v; i++) nextList[i] = new List<int>();//リストの宣言
  
    for(int i = 0; i < e; i++)
    {
      string[] inputa = Console.ReadLine().Split(' ');
      int a = int.Parse(inputa[0]);
      int b = int.Parse(inputa[1]);
      nextList[a].Add(b);
      nextList[b].Add(a);
    }
    ArticulationPoints();
	}

  static void ArticulationPoints()//関節点を求める
  {
    for(int i = 0; i < v; i++) checkedVertex[i] = false;
    timer = 1;
    DFS(0,-1);//深さ優先探索

    int np = 0;
    for(int i = 1; i < v; i++)
    {
      if(parent[i] == 0) np++;
      else if(prenum[parent[i]] <= lowest[i]) answers.Add(parent[i]);
    }
    if(np > 1) answers.Add(0);

    var memo = answers.Distinct().ToArray();
    Array.Sort(memo);//ソートして重複を除く
    
    var answerText = new StringBuilder();//解答の出力
    for(int i = 0; i < memo.Length; i++)
    {
      answerText.AppendLine(memo[i].ToString());
    }
    Console.Write(answerText);
  }

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

    checkedVertex[current] = true;
    int nextVertex = 0;

    for(int i = 0; i < nextList[current].Count(); i++)
    {
      nextVertex = nextList[current][i];
      if(!checkedVertex[nextVertex])
      {
        parent[nextVertex] = current;
        DFS(nextVertex, current);
        lowest[current] = Math.Min(lowest[current], lowest[nextVertex]);
      }else if(nextVertex != prev)
      {
        lowest[current] = Math.Min(lowest[current], prenum[nextVertex]);
      }
    }
  }
  
}