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|  s 0  t 0  s 1  t 1 : 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.  s i and t i 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 (Python):
from sys import stdin
from collections import deque

def read_graph(n, k):
    A = [ [] for _ in range(n) ]
    for _ in range(k):
        line = stdin.readline().strip().split()
        A[int(line[0])].append(int(line[1]))
        A[int(line[1])].append(int(line[0]))
    return A

def art_points(n, A):
    S = deque([])
    color = ["WHITE"] * n
    time = 0
    prenum = [0] * n
    parent = [0] * n
    lowest = [0] * n
    ap = []

    def dfs(u):
        nonlocal S
        nonlocal color
        nonlocal time
        nonlocal prenum
        nonlocal parent
        nonlocal lowest
        S.appendleft(u)
        color[u] = "GRAY"
        prenum[u] = lowest[u] = time
        parent[u] = -1
        time += 1

        while S:
            try:
                w = S[1]
            except IndexError:
                w = -1
            u = S[0]
            colors = [color[v] for v in A[u]]
            if "WHITE" in colors:
                for v in A[u]:
                    if color[v] == "WHITE":
                        parent[v] = u
                        color[v] = "GRAY"
                        prenum[v] = lowest[v] = time
                        time += 1
                        S.appendleft(v)
                        break
            else:
                for v in A[u]:
                    if color[v] == "GRAY" and v != w:
                        
                        lowest[u] = min(lowest[u], prenum[v])
                if parent[u] != -1:
                    
                    lowest[parent[u]] = min(lowest[u], lowest[parent[u]])
                S.popleft()
                color[u] = "BLACK"
                time += 1

    def obtain_ap():
        np = 0
        for i in range(n):
            p = parent[i]
            if p == 0:
                np += 1
            elif prenum[p] <= lowest[i]:
                if p not in ap:
                    ap.append(p)
        if np > 1:
            ap.append(0)

    dfs(0)
    obtain_ap()

    return ap

n, k = [int(i) for i in input().split()]
A = read_graph(n, k)
ap = art_points(n, A)
for i in sorted(ap):
    if i != -1:
        print(i)

Solution (Python):
import sys

sys.setrecursionlimit(int(1e6))

n, m = map(int, input().split())

edges = {}

for i in range(m):
    s, t = map(int, input().split())
    if s not in edges:
        edges[s] = set()
    if t not in edges:
        edges[t] = set()
    edges[s].add(t)
    edges[t].add(s)

order = [0] * n
lowlink = [0] * n
visited = set()
articulation = set()


def dfs(v, p, i):
    visited.add(v)

    i += 1
    lowlink[v] = order[v] = i

    is_articulation = False
    cnt = 0

    if v not in edges:
        return

    for t in edges[v]:
        if t not in visited:
            cnt += 1
            dfs(t, v, i)
            lowlink[v] = min(lowlink[v], lowlink[t])
            if p != -1 and order[v] <= lowlink[t]:
                is_articulation = True
        elif t != p:
            lowlink[v] = min(lowlink[v], order[t])

    if p == -1 and cnt > 1:
        is_articulation = True

    if is_articulation:
        articulation.add(v)


k = 0
for i in range(n):
    if i not in visited:
        dfs(i, -1, k)

for art in sorted(articulation):
    print(art)

Solution (Python):
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)
v, e = map(int, input().split())
edges = [[] for _ in range(v)]
for _ in range(e):
    s, t = map(int, input().split())
    edges[s].append(t)
    edges[t].append(s)

lowlinks = LowLinks(edges, v)
lowlinks.build()
if lowlinks.articulations: print(*sorted(lowlinks.articulations),sep="\n")

Solution (Python):
from sys import setrecursionlimit
setrecursionlimit(100000)
def inpl():
  return tuple(map(int, input().split()))
V, E = inpl()
graph = [[] for i in range(V)]

for _ in range(E):
  s, t = inpl()
  graph[s].append(t)
  graph[t].append(s)

prenum = [-1] * V
lowest = [float("inf")]*V
found = [False] * V
parent = [-1] *V

result = set()
root = 0

def DFS(i, c, prev):
  global root
  prenum[i] = c
  lowest[i] = c
  found[i] = True

  for p in graph[i]:
    if found[p]:
      if p != prev:
        lowest[i] = min(lowest[i], prenum[p])
    else:
      c = DFS(p, c+1, i)
      lowest[i] = min(lowest[i], lowest[p])

  if prenum[prev] <= lowest[i]:
    result.add(prev)
  parent[i] = prev

  return c

DFS(0, 1, 0)

if parent.count(0) <= 2:
  result = result.difference([0])

for r in sorted(result):
  print(r)

Solution (Python):



class Edge:
    __slots__ = ('v', 'w')

    def __init__(self, v, w):
        self.v = v
        self.w = w

    def either(self):
        return self.v

    def other(self, v):
        if v == self.v:
            return self.w
        else:
            return self.v


class Graph:
    def __init__(self, v):
        self.v = v
        self._edges = [[] for _ in range(v)]

    def add(self, e):
        self._edges[e.v].append(e)
        self._edges[e.w].append(e)

    def adj(self, v):
        return self._edges[v]

    def edges(self):
        for es in self._edges:
            for e in es:
                yield e


def articulation_points(graph):
    visited = [0] * graph.v
    low = [0] * graph.v
    parent = [-1] * graph.v

    s = 0
    children = 0
    visit = 0
    stack = [s]
    vs = set()

    while stack:
        v = stack.pop()
        if not visited[v]:
            visit += 1
            visited[v] = visit
            low[v] = visit

        for e in graph.adj(v):
            w = e.other(v)
            if not visited[w]:
                parent[w] = v
                if v == s:
                    children += 1
                stack.append(v)
                stack.append(w)
                break
            elif w != parent[v]:
                low[v] = min(low[v], visited[w])
        else:
            u = parent[v]
            if u < 0:
                pass
            elif parent[u] < 0:
                if children > 1:
                    vs.add(u)
            else:
                if low[v] >= visited[u]:
                    vs.add(u)
                low[u] = min(low[u], low[v])

    return vs


def run():
    v, e = [int(i) for i in input().split()]
    graph = Graph(v)

    for _ in range(e):
        s, t = [int(i) for i in input().split()]
        edge = Edge(s, t)
        graph.add(edge)

    for v in sorted(articulation_points(graph)):
        print(v)


if __name__ == '__main__':
    run()

Solution (Python):
import sys

sys.setrecursionlimit(100000)

timer = 0

def dfs(current, prev, g, visited, prenum, parent, lowest):
    global timer
    prenum[current] = timer
    lowest[current] = timer
    timer += 1

    visited[current] = True

    for i in range(len(g[current])):
        next_node = g[current][i]
        if not visited[next_node]:
            parent[next_node] = current
            dfs(next_node, current, g, visited, prenum, parent, lowest)
            lowest[current] = min(lowest[current], lowest[next_node])
        elif next_node != prev:
            lowest[current] = min(lowest[current], prenum[next_node])


def art_points(n, g):
    visited = [False] * n
    INFTY = 1 << 20
    prenum = [INFTY] * n
    parent = [INFTY] * n
    parent[0] = -1
    lowest = [INFTY] * n
    global timer
    timer = 1
    dfs(0, -1, g, visited, prenum, parent, lowest)

    ap = set()
    np = 0
    for i in range(1, n):
        p = parent[i]
        if p == 0:
            np += 1
        elif prenum[p] <= lowest[i]:
            ap.add(p)
    if np > 1:
        ap.add(0)
    for line in sorted(ap):
        print(line)


if __name__ == '__main__':
    n, m = [int(v) for v in input().split()]
    g = [[] for i in range(n)]
    for i in range(m):
        s, t = [int(v) for v in input().split()]
        g[s].append(t)
        g[t].append(s)

    art_points(n, g)