import sys

sys.setrecursionlimit(10**6)

def get_articulation_points(G, N, start=0):

    v_min = [0]*N; order = [None]*N

    result = []; count = 0

    def dfs(v, prev):

        nonlocal count

        r_min = order[v] = count

        fcnt = 0; p_art = 0

        count += 1

        for w in G[v]:

            if w == prev:

                continue

            if order[w] is None:

                ret = dfs(w, v)

                p_art |= (order[v] <= ret)

                r_min = min(r_min, ret)

                fcnt += 1

            else:

                r_min = min(r_min, order[w])

        p_art |= (r_min == order[v] and len(G[v]) > 1)

        if (prev == -1 and fcnt > 1) or (prev != -1 and p_art):

            result.append(v)

        return r_min

    dfs(start, -1)

    return result



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

G = [[] for i in range(n)]

for i in range(m):

    s, t = map(int, input().split())

    G[s].append(t)

    G[t].append(s)

*_,=map(print,sorted(get_articulation_points(G, n)))

import sys

sys.setrecursionlimit(10**6)

readline = sys.stdin.readline

write = sys.stdout.write



N, M = list(map(int, readline().split()))



G = [[] for i in range(N)]

for i in range(M):

    u, v = list(map(int, readline().split()))

    G[u].append(v)

    G[v].append(u)



# a chain decomposition

def construct(G, N):

    P = [0]*N

    G0 = [[] for i in range(N)]

    V = []

    lb = [0]*N

    def dfs(v, p):

        P[v] = p

        V.append(v)

        lb[v] = len(V)

        for w in G[v]:

            if w == p:

                continue

            if lb[w]:

                if lb[v] < lb[w]:

                    # a backedge

                    G0[v].append(w)

                continue

            # a tree edge

            dfs(w, v)

    dfs(0, -1)



    used = [0]*N

    first = 1

    B = []

    used[0] = 1

    ap = [0]*N

    for u in V:

        if not used[u]:

            # (u, p) is a bridge

            p = P[u]

            B.append((u, p) if u < p else (p, u))

            if len(G[u]) > 1:

                ap[u] = 1

            if len(G[p]) > 1:

                ap[p] = 1

        cycle = 0

        for v in G0[u]:

            w = v

            while w != u and not used[w]:

                used[w] = 1

                w = P[w]

            if w == u:

                cycle = 1

        if cycle:

            if not first:

                ap[u] = 1

            first = 0

    # v is a cut vertex

    A = [v for v in range(N) if ap[v]]



    return B, A



B, A = construct(G, N)



for v in A:

    write("%d\n" % v)

import sys

sys.setrecursionlimit(10**6)


def get_articulation_points(G, N, start=0):
    v_min = [0] * N
    order = [None] * N
    result = []
    count = 0

    def dfs(v, prev):
        nonlocal count
        r_min = order[v] = count
        fcnt = 0
        p_art = 0
        count += 1
        for w in G[v]:
            if w == prev:
                continue
            if order[w] is None:
                ret = dfs(w, v)
                p_art |= order[v] <= ret
                r_min = min(r_min, ret)
                fcnt += 1
            else:
                r_min = min(r_min, order[w])
        p_art |= r_min == order[v] and len(G[v]) > 1
        if (prev == -1 and fcnt > 1) or (prev != -1 and p_art):
            result.append(v)
        return r_min

    dfs(start, -1)
    return result


n, m = map(int, input().split())
G = [[] for i in range(n)]
for i in range(m):
    s, t = map(int, input().split())
    G[s].append(t)
    G[t].append(s)
(*_,) = map(print, sorted(get_articulation_points(G, n)))

import sys

sys.setrecursionlimit(10**6)
readline = sys.stdin.readline
write = sys.stdout.write
N, M = list(map(int, readline().split()))
G = [[] for i in range(N)]
for i in range(M):
    u, v = list(map(int, readline().split()))
    G[u].append(v)
    G[v].append(u)
# a chain decomposition
def construct(G, N):
    P = [0] * N
    G0 = [[] for i in range(N)]
    V = []
    lb = [0] * N

    def dfs(v, p):
        P[v] = p
        V.append(v)
        lb[v] = len(V)
        for w in G[v]:
            if w == p:
                continue
            if lb[w]:
                if lb[v] < lb[w]:
                    # a backedge
                    G0[v].append(w)
                continue
            # a tree edge
            dfs(w, v)

    dfs(0, -1)
    used = [0] * N
    first = 1
    B = []
    used[0] = 1
    ap = [0] * N
    for u in V:
        if not used[u]:
            # (u, p) is a bridge
            p = P[u]
            B.append((u, p) if u < p else (p, u))
            if len(G[u]) > 1:
                ap[u] = 1
            if len(G[p]) > 1:
                ap[p] = 1
        cycle = 0
        for v in G0[u]:
            w = v
            while w != u and not used[w]:
                used[w] = 1
                w = P[w]
            if w == u:
                cycle = 1
        if cycle:
            if not first:
                ap[u] = 1
            first = 0
    # v is a cut vertex
    A = [v for v in range(N) if ap[v]]
    return B, A


B, A = construct(G, N)
for v in A:
    write("%d\n" % v)

+readline = sys.stdin.readline +write = sys.stdout.write +N, M = list(map(int, readline().split())) +G = [[] for i in range(N)] +for i in range(M): +    u, v = list(map(int, readline().split())) +    G[u].append(v) +    G[v].append(u) +# a chain decomposition +def construct(G, N): +    P = [0] * N +    G0 = [[] for i in range(N)] +    V = [] +    lb = [0] * N + +    def dfs(v, p): +        P[v] = p +        V.append(v) +        lb[v] = len(V) +        for w in G[v]: +            if w == p: +                continue +            if lb[w]: +                if lb[v] < lb[w]: +                    # a backedge +                    G0[v].append(w) +                continue +            # a tree edge +            dfs(w, v) + +    dfs(0, -1) +    used = [0] * N +    first = 1 +    B = [] +    used[0] = 1 +    ap = [0] * N +    for u in V: +        if not used[u]: +            # (u, p) is a bridge +            p = P[u] +            B.append((u, p) if u < p else (p, u)) +            if len(G[u]) > 1: +                ap[u] = 1 +            if len(G[p]) > 1: +                ap[p] = 1 +        cycle = 0 +        for v in G0[u]: +            w = v +            while w != u and not used[w]: +                used[w] = 1 +                w = P[w] +            if w == u: +                cycle = 1 +        if cycle: +            if not first: +                ap[u] = 1 +            first = 0 +    # v is a cut vertex +    A = [v for v in range(N) if ap[v]] +    return B, A -def get_articulation_points(G, N, start=0): -    v_min = [0] * N -    order = [None] * N -    result = [] -    count = 0 - -    def dfs(v, prev): -        nonlocal count -        r_min = order[v] = count -        fcnt = 0 -        p_art = 0 -        count += 1 -        for w in G[v]: -            if w == prev: -                continue -            if order[w] is None: -                ret = dfs(w, v) -                p_art |= order[v] <= ret -                r_min = min(r_min, ret) -                fcnt += 1 -            else: -                r_min = min(r_min, order[w]) -        p_art |= r_min == order[v] and len(G[v]) > 1 -        if (prev == -1 and fcnt > 1) or (prev != -1 and p_art): -            result.append(v) -        return r_min - -    dfs(start, -1) -    return result - - -n, m = map(int, input().split()) -G = [[] for i in range(n)] -for i in range(m): -    s, t = map(int, input().split()) -    G[s].append(t) -    G[t].append(s) -(*_,) = map(print, sorted(get_articulation_points(G, n))) +B, A = construct(G, N) +for v in A: +    write("%d\n" % v)