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++14 (judge verdict: Accepted)

#include <vector>
#include <algorithm>

struct low_link {
    int n;
    std::vector<std::vector<int>> adj;
    std::vector<int> ord, low;
    std::vector<int> articulations;
    std::vector<std::pair<int, int>> bridges;
    low_link(const std::vector<std::vector<int>> &adj) : n(adj.size()), adj(adj), ord(n), low(n) {
        std::vector<bool> visited(n);
        int k = 0;
        auto dfs = [&](auto &&self, int cur, int par) -> void {
            visited[cur] = true;
            ord[cur] = k++;
            low[cur] = ord[cur];
            int cnt = 0;
            bool is_articulation = false;
            for (int to : adj[cur]) {
                if (!visited[to]) {
                    cnt++;
                    self(self, to, cur);
                    low[cur] = std::min(low[cur], low[to]);
                    is_articulation |= ord[cur] <= low[to];
                    if (ord[cur] < low[to]) { bridges.emplace_back(std::minmax(cur, to)); }
                } else if (to != par) { low[cur] = std::min(low[cur], ord[to]); }
            }
            if (par == -1) { is_articulation = cnt >= 2; }
            if (is_articulation) { articulations.emplace_back(cur); }
        };
        dfs(dfs, 0, -1);
    }
};

#include <bits/stdc++.h>
using namespace std;

int main() {
    int V, E;
    cin >> V >> E;
    vector<vector<int>> adj(V);
    for (int i = 0; i < E; i++) {
        int s, t;
        cin >> s >> t;
        adj[s].emplace_back(t);
        adj[t].emplace_back(s);
    }
    low_link ll(adj);
    sort(ll.articulations.begin(), ll.articulations.end());
    for (auto p:ll.articulations) { cout << p << endl; }
}