human
What is a Python program to find articulation points of a given undirected graph G(V, E) given the following:
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.

Constraints

* 1 ≤ |V| ≤ 100,000
* 0 ≤ |E| ≤ 100,000
* The graph is connected
* There are no parallel edges
* There are no self-loops

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.

Examples

Input

4 4
0 1
0 2
1 2
2 3

Output

2

Input

5 4
0 1
1 2
2 3
3 4

Output

1
2
3
The above is tricky. Write me a correct solution in PYTHON3.
assistant
#Here is Python program to find articulation points of a given undirected graph G(V, E).

#関節点(そのノードを除くとグラフが非連結になる点)
import sys
class LowLinks:
    def __init__(self, edges, v, root=0):
        self.edges = edges
        self.root = root
        self.ord = [None] * v
        self.low = [None] * v
        self.cnt = 0
        self.bridges = []
        self.articulations = set()
        self.par = [None] * v

    def build(self):
        self.search(self.root)

    def search(self, x):
        self.ord[x] = self.cnt
        self.low[x] = self.cnt
        self.cnt += 1
        dim = 0
        for to in self.edges[x]:
            if to == self.par[x]:continue
            if self.ord[to] != None:
                self.low[x] = min(self.low[x], self.ord[to])
            else:
                self.par[to] = x
                self.search(to)
                dim += 1
                self.low[x] = min(self.low[x], self.low[to])

                if x != self.root and self.ord[x] <= self.low[to]:
                    self.articulations.add(x)

            if x == self.root and dim > 1:
                self.articulations.add(x)

            if self.ord[x] < self.low[to]:
                self.bridges.append((x, to))

sys.setrecursionlimit(1000000)
n,m=map(int,input().split())
edges=[[] for _ in range(n)]
for _ in range(m):
    s, t = map(int, input().split())
    edges[s].append(t)
    edges[t].append(s)

l=LowLinks(edges,n)
l.build()
for i in sorted(l.articulations):
    print(i)