Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

from sys import stdin

UNVISITED, VISITED_IN_STACK, POPPED_OUT = 0, 1, 2


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
        # undirected graph
        init_adj_table[v_to].append(v_from)
    return init_adj_table


def graph_dfs(current, prev):
    global timer
    pre_v[current] = lowest_v[current] = timer
    timer += 1

    color[current] = VISITED_IN_STACK

    for adj in adj_table[current]:
        if color[adj] is UNVISITED:
            parent_v[adj] = current

            graph_dfs(adj, current)

            lowest_v[current] = min(lowest_v[current], lowest_v[adj])
        elif adj is not prev:
            lowest_v[current] = min(lowest_v[current], pre_v[adj])

    return None


def art_points():
    graph_dfs(0, -1)

    v_count = 0
    for j in range(1, vertices):
        parent = parent_v[j]
        if parent == init_vertex_index:
            v_count += 1
        elif pre_v[parent] <= lowest_v[j]:
            ans.add(parent)

    if v_count > 1:
        ans.add(init_vertex_index)

    return ans


if __name__ == '__main__':
    _input = stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:])
    pre_v, parent_v, lowest_v = ([-1] * vertices for _ in range(3))
    init_adj_table = tuple([] for _ in range(vertices))

    timer = 1
    # root
    init_vertex_index = 0

    ans = set()
    color = [UNVISITED] * vertices

    adj_table = generate_adj_table(v_info)

    res = art_points()
    if not res:
        pass
    else:
        # print(*sorted(art_points()), sep='\n')
        print(*sorted(res), sep='\n')

Fixed submission:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

import sys

sys.setrecursionlimit(int(1e5))


def dfs_Tarjan(current, visited, disc, low, parent):
    global timer
    children = 0
    visited[current] = True
    disc[current] = low[current] = timer
    timer += 1

    for adj in adj_table[current]:
        if not visited[adj]:
            parent[adj] = current
            children += 1
            dfs_Tarjan(adj, visited, disc, low, parent)
            low[current] = min(low[current], low[adj])
            if parent[current] == -1 and children > 1:
                art_set.add(current)
            elif parent[current] != -1 and low[adj] >= disc[current]:
                art_set.add(current)

        elif adj != parent[current]:
            low[current] = min(low[current], disc[adj])

    return None


def dfs_init():
    parent = [-1] * v_num
    visited = [False] * v_num
    disc, low = ([float('inf')] * v_num for _ in range(2))

    for v in range(v_num):
        if not visited[v]:
            dfs_Tarjan(v, visited, disc, low, parent)

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    v_num, e_num = map(int, _input[0].split())
    edges = map(lambda x: x.split(), _input[1:])

    adj_table = tuple([] for _ in range(v_num))
    for edge in edges:
        source, target = map(int, edge)
        adj_table[source].append(target)
        adj_table[target].append(source)

    timer = 0
    art_set = set()
    # generate articulation points set
    dfs_init()
    if art_set:
        print(*sorted(art_set), sep='\n')

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

from sys import stdin

UNVISITED, VISITED_IN_STACK, POPPED_OUT = 0, 1, 2


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
        # undirected graph
        init_adj_table[v_to].append(v_from)
    return init_adj_table


def graph_dfs(current, prev):
    global timer
    pre_v[current] = lowest_v[current] = timer
    timer += 1

    color[current] = VISITED_IN_STACK

    for adj in adj_table[current]:
        if color[adj] is UNVISITED:
            parent_v[adj] = current

            graph_dfs(adj, current)

            lowest_v[current] = min(lowest_v[current], lowest_v[adj])
        elif adj is not prev:
            lowest_v[current] = min(lowest_v[current], pre_v[adj])

    return None


def art_points():
    graph_dfs(0, -1)

    v_count = 0
    for j in range(1, vertices):
        parent = parent_v[j]
        if parent == init_vertex_index:
            v_count += 1
        elif pre_v[parent] <= lowest_v[j]:
            ans.add(parent)

    if v_count > 1:
        ans.add(init_vertex_index)

    return ans


if __name__ == '__main__':
    _input = stdin.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:])
    pre_v, parent_v, lowest_v = ([-1] * vertices for _ in range(3))
    init_adj_table = tuple([] for _ in range(vertices))

    timer = 1
    # root
    init_vertex_index = 0

    ans = set()
    color = [UNVISITED] * vertices

    adj_table = generate_adj_table(v_info)

    res = art_points()
    if not res:
        pass
    else:
        # print(*sorted(art_points()), sep='\n')
        print(*sorted(res), sep='\n')

Fixed submission:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

import sys

sys.setrecursionlimit(int(1e5))


def dfs_Tarjan(current, visited, disc, low, parent):
    global timer
    children = 0
    visited[current] = True
    disc[current] = low[current] = timer
    timer += 1

    for adj in adj_table[current]:
        if not visited[adj]:
            parent[adj] = current
            children += 1
            dfs_Tarjan(adj, visited, disc, low, parent)
            low[current] = min(low[current], low[adj])
            if parent[current] == -1 and children > 1:
                art_set.add(current)
            elif parent[current] != -1 and low[adj] >= disc[current]:
                art_set.add(current)

        elif adj != parent[current]:
            low[current] = min(low[current], disc[adj])

    return None


def dfs_init():
    parent = [-1] * v_num
    visited = [False] * v_num
    disc, low = ([float('inf')] * v_num for _ in range(2))

    for v in range(v_num):
        if not visited[v]:
            dfs_Tarjan(v, visited, disc, low, parent)

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    v_num, e_num = map(int, _input[0].split())
    edges = map(lambda x: x.split(), _input[1:])

    adj_table = tuple([] for _ in range(v_num))
    for edge in edges:
        source, target = map(int, edge)
        adj_table[source].append(target)
        adj_table[target].append(source)

    timer = 0
    art_set = set()
    # generate articulation points set
    dfs_init()
    if art_set:
        print(*sorted(art_set), sep='\n')

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

from sys import stdin

UNVISITED, VISITED_IN_STACK, POPPED_OUT = 0, 1, 2


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
        # undirected graph
        init_adj_table[v_to].append(v_from)
    return init_adj_table


def graph_dfs(current, prev):
    global timer
    pre_v[current] = lowest_v[current] = timer
    timer += 1

    color[current] = VISITED_IN_STACK

    for adj in adj_table[current]:
        if color[adj] is UNVISITED:
            parent_v[adj] = current

            # recursive dfs
            graph_dfs(adj, current)

            lowest_v[current] = min(lowest_v[current], lowest_v[adj])
        elif adj is not prev:
            lowest_v[current] = min(lowest_v[current], pre_v[adj])

    return None


def art_points():
    graph_dfs(0, -1)

    v_count = 0
    for j in range(1, vertices):
        parent = parent_v[j]
        if parent == init_vertex_index:
            v_count += 1
        elif pre_v[parent] <= lowest_v[j]:
            ans.add(parent)

    if v_count > 1:
        ans.add(init_vertex_index)

    return ans


if __name__ == '__main__':
    # _input = stdin.readlines()
    _in = open('test.txt', 'rt')
    _input = _in.readlines()
    # raise SystemExit
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:])
    pre_v, parent_v, lowest_v = ([0] * vertices for _ in range(3))
    init_adj_table = tuple([] for _ in range(vertices))

    timer = 1
    # root
    init_vertex_index = 0

    ans = set()
    color = [UNVISITED] * vertices

    adj_table = generate_adj_table(v_info)

    res = art_points()
    if not res:
        pass
    else:
        # print(*sorted(art_points()), sep='\n')
        print(*sorted(res), sep='\n')

Fixed submission:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

import sys

sys.setrecursionlimit(int(1e5))


def dfs_Tarjan(current, visited, disc, low, parent):
    global timer
    children = 0
    visited[current] = True
    disc[current] = low[current] = timer
    timer += 1

    for adj in adj_table[current]:
        if not visited[adj]:
            parent[adj] = current
            children += 1
            dfs_Tarjan(adj, visited, disc, low, parent)
            low[current] = min(low[current], low[adj])
            if parent[current] == -1 and children > 1:
                art_set.add(current)
            elif parent[current] != -1 and low[adj] >= disc[current]:
                art_set.add(current)

        elif adj != parent[current]:
            low[current] = min(low[current], disc[adj])

    return None


def dfs_init():
    parent = [-1] * v_num
    visited = [False] * v_num
    disc, low = ([float('inf')] * v_num for _ in range(2))

    for v in range(v_num):
        if not visited[v]:
            dfs_Tarjan(v, visited, disc, low, parent)

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    v_num, e_num = map(int, _input[0].split())
    edges = map(lambda x: x.split(), _input[1:])

    adj_table = tuple([] for _ in range(v_num))
    for edge in edges:
        source, target = map(int, edge)
        adj_table[source].append(target)
        adj_table[target].append(source)

    timer = 0
    art_set = set()
    # generate articulation points set
    dfs_init()
    if art_set:
        print(*sorted(art_set), sep='\n')

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

from sys import stdin

UNVISITED, VISITED_IN_STACK, POPPED_OUT = 0, 1, 2


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
        # undirected graph
        init_adj_table[v_to].append(v_from)
    return init_adj_table


def graph_dfs(current, prev):
    global timer
    pre_v[current] = lowest_v[current] = timer
    timer += 1

    color[current] = VISITED_IN_STACK

    for adj in adj_table[current]:
        if color[adj] is UNVISITED:
            parent_v[adj] = current

            # recursive dfs
            graph_dfs(adj, current)

            lowest_v[current] = min(lowest_v[current], lowest_v[adj])
        elif adj is not prev:
            lowest_v[current] = min(lowest_v[current], pre_v[adj])

    return None


def art_points():
    graph_dfs(0, -1)

    v_count = 0
    for j in range(1, vertices):
        parent = parent_v[j]
        if parent == init_vertex_index:
            v_count += 1
        elif pre_v[parent] <= lowest_v[j]:
            ans.add(parent)

    if v_count > 1:
        ans.add(init_vertex_index)

    return ans


if __name__ == '__main__':
    _input = stdin.readlines()
    # raise SystemExit
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:])
    pre_v, parent_v, lowest_v = ([0] * vertices for _ in range(3))
    init_adj_table = tuple([] for _ in range(vertices))

    timer = 1
    # root
    init_vertex_index = 0

    ans = set()
    color = [UNVISITED] * vertices

    adj_table = generate_adj_table(v_info)

    res = art_points()
    if not res:
        pass
    else:
        # print(*sorted(art_points()), sep='\n')
        print(*sorted(res), sep='\n')

Fixed submission:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

import sys

sys.setrecursionlimit(int(1e5))


def dfs_Tarjan(current, visited, disc, low, parent):
    global timer
    children = 0
    visited[current] = True
    disc[current] = low[current] = timer
    timer += 1

    for adj in adj_table[current]:
        if not visited[adj]:
            parent[adj] = current
            children += 1
            dfs_Tarjan(adj, visited, disc, low, parent)
            low[current] = min(low[current], low[adj])
            if parent[current] == -1 and children > 1:
                art_set.add(current)
            elif parent[current] != -1 and low[adj] >= disc[current]:
                art_set.add(current)

        elif adj != parent[current]:
            low[current] = min(low[current], disc[adj])

    return None


def dfs_init():
    parent = [-1] * v_num
    visited = [False] * v_num
    disc, low = ([float('inf')] * v_num for _ in range(2))

    for v in range(v_num):
        if not visited[v]:
            dfs_Tarjan(v, visited, disc, low, parent)

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    v_num, e_num = map(int, _input[0].split())
    edges = map(lambda x: x.split(), _input[1:])

    adj_table = tuple([] for _ in range(v_num))
    for edge in edges:
        source, target = map(int, edge)
        adj_table[source].append(target)
        adj_table[target].append(source)

    timer = 0
    art_set = set()
    # generate articulation points set
    dfs_init()
    if art_set:
        print(*sorted(art_set), sep='\n')

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

import sys

sys.setrecursionlimit(int(3e6))
UNVISITED, VISITED_IN_STACK, POPPED_OUT = 0, 1, 2


def generate_adj_table(_v_info):
    for v_detail in _v_info:
        v_from, v_to = map(int, v_detail)
        init_adj_table[v_from].append(v_to)
        # undirected graph
        init_adj_table[v_to].append(v_from)
    return init_adj_table


def graph_dfs(current, prev):
    global timer
    pre_v[current] = lowest_v[current] = timer
    timer += 1

    color[current] = VISITED_IN_STACK

    for adj in adj_table[current]:
        if color[adj] is UNVISITED:
            parent_v[adj] = current

            # recursive dfs
            graph_dfs(adj, current)

            lowest_v[current] = min(lowest_v[current], lowest_v[adj])
        elif adj is not prev:
            lowest_v[current] = min(lowest_v[current], pre_v[adj])

    return None


def art_points():
    graph_dfs(dfs_root, -1)

    np = 0
    for v in range(1, vertices):
        parent = parent_v[v]
        if parent is dfs_root:
            np += 1
        elif pre_v[parent] <= lowest_v[v]:
            ans.add(parent)

    if np > 1:
        ans.add(dfs_root)

    return ans


if __name__ == '__main__':
    # _input = sys.stdin.readlines()
    with open('test.txt', 'rt') as _in:
        _input = _in.readlines()
    vertices, edges = map(int, _input[0].split())
    v_info = map(lambda x: x.split(), _input[1:])
    pre_v, parent_v, lowest_v = ([0] * vertices for _ in range(3))
    init_adj_table = tuple([] for _ in range(vertices))

    timer = 1
    # root
    dfs_root = 0

    ans = set()
    color = [UNVISITED] * vertices

    adj_table = generate_adj_table(v_info)

    res = art_points()
    if not res:
        pass
    else:
        # print(*sorted(art_points()), sep='\n')
        print(*sorted(res), sep='\n')

Fixed submission:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

import sys

sys.setrecursionlimit(int(1e5))


def dfs_Tarjan(current, visited, disc, low, parent):
    global timer
    children = 0
    visited[current] = True
    disc[current] = low[current] = timer
    timer += 1

    for adj in adj_table[current]:
        if not visited[adj]:
            parent[adj] = current
            children += 1
            dfs_Tarjan(adj, visited, disc, low, parent)
            low[current] = min(low[current], low[adj])
            if parent[current] == -1 and children > 1:
                art_set.add(current)
            elif parent[current] != -1 and low[adj] >= disc[current]:
                art_set.add(current)

        elif adj != parent[current]:
            low[current] = min(low[current], disc[adj])

    return None


def dfs_init():
    parent = [-1] * v_num
    visited = [False] * v_num
    disc, low = ([float('inf')] * v_num for _ in range(2))

    for v in range(v_num):
        if not visited[v]:
            dfs_Tarjan(v, visited, disc, low, parent)

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    v_num, e_num = map(int, _input[0].split())
    edges = map(lambda x: x.split(), _input[1:])

    adj_table = tuple([] for _ in range(v_num))
    for edge in edges:
        source, target = map(int, edge)
        adj_table[source].append(target)
        adj_table[target].append(source)

    timer = 0
    art_set = set()
    # generate articulation points set
    dfs_init()
    if art_set:
        print(*sorted(art_set), sep='\n')

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

import sys

sys.setrecursionlimit(int(1e4))


def dfs_Tarjan(current):
    global timer
    children = 0
    visited[current] = True
    disc[current] = low[current] = timer
    timer += 1

    for adj in adj_table[current]:
        if not visited[adj]:
            parent[adj] = current
            children += 1
            dfs_Tarjan(adj)
            low[current] = min(low[current], low[adj])
            # current vertex is the root of DFS tree
            if parent[current] == -1 and children > 1:
                art_set.add(current)
            elif parent[current] != -1 and low[adj] >= disc[current]:
                art_set.add(current)

        elif adj != parent[current]:
            low[current] = min(low[current], disc[adj])

    return None


def dfs_init():
    for v in range(v_num):
        if not visited[v]:
            dfs_Tarjan(v)

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    v_num, e_num = map(int, _input[0].split())
    edges = map(lambda x: x.split(), _input[1:])

    adj_table = tuple([] for _ in range(v_num))
    for edge in edges:
        source, target = map(int, edge)
        adj_table[source].append(target)
        adj_table[target].append(source)

    timer = 0
    art_set = set()
    parent = [-1] * v_num
    visited = [False] * v_num
    disc, low = ([float('inf')] * v_num for _ in range(2))

    dfs_init()
    if art_set:
        print(*sorted(art_set), sep='\n')

Fixed submission:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

input:
5 4
0 1
1 2
2 3
3 4

output:
1
2
3
"""

import sys

sys.setrecursionlimit(int(1e5))


def dfs_Tarjan(current, visited, disc, low, parent):
    global timer
    children = 0
    visited[current] = True
    disc[current] = low[current] = timer
    timer += 1

    for adj in adj_table[current]:
        if not visited[adj]:
            parent[adj] = current
            children += 1
            dfs_Tarjan(adj, visited, disc, low, parent)
            low[current] = min(low[current], low[adj])
            if parent[current] == -1 and children > 1:
                art_set.add(current)
            elif parent[current] != -1 and low[adj] >= disc[current]:
                art_set.add(current)

        elif adj != parent[current]:
            low[current] = min(low[current], disc[adj])

    return None


def dfs_init():
    parent = [-1] * v_num
    visited = [False] * v_num
    disc, low = ([float('inf')] * v_num for _ in range(2))

    for v in range(v_num):
        if not visited[v]:
            dfs_Tarjan(v, visited, disc, low, parent)

    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    v_num, e_num = map(int, _input[0].split())
    edges = map(lambda x: x.split(), _input[1:])

    adj_table = tuple([] for _ in range(v_num))
    for edge in edges:
        source, target = map(int, edge)
        adj_table[source].append(target)
        adj_table[target].append(source)

    timer = 0
    art_set = set()
    # generate articulation points set
    dfs_init()
    if art_set:
        print(*sorted(art_set), sep='\n')