Buggy python submission (verdict: Time Limit Exceeded):
import sys

import numpy as np

sys.setrecursionlimit(2 ** 31 - 1)
INF = float('inf')

N = int(sys.stdin.readline())
AB = [list(map(int, sys.stdin.readline().split())) for _ in range(N - 1)]

graph = [set() for _ in range(N + 1)]
for a, b in AB:
    graph[a].add(b)
    graph[b].add(a)


def dfs(to, path):
    if path[-1] == to:
        return path
    v = path[-1]
    prev = path[-2] if len(path) >= 2 else None

    for u in graph[v]:
        if u != prev:
            ret = dfs(to, path + [u])
            if ret:
                return ret
    return None


# 1 から N までのパス
path = dfs(N, [1])
cut = (len(path) - 1) // 2
fennec = path[:cut + 1]
snuke = path[cut + 1:]

fixed = np.zeros(N + 1, dtype=str)
fixed[fennec] = 'f'
fixed[snuke] = 's'

while fennec:
    v = fennec.pop()
    for u in graph[v]:
        if not fixed[u]:
            fixed[u] = 'f'
            fennec.append(u)
while snuke:
    v = snuke.pop()
    for u in graph[v]:
        if not fixed[u]:
            fixed[u] = 's'
            snuke.append(u)

if sum(fixed == 'f') > sum(fixed == 's'):
    print('Fennec')
else:
    print('Snuke')


Fixed submission:
import sys

import numpy as np

sys.setrecursionlimit(2 ** 31 - 1)
INF = float('inf')

N = int(sys.stdin.readline())
AB = [list(map(int, sys.stdin.readline().split())) for _ in range(N - 1)]

graph = [[] for _ in range(N + 1)]
for a, b in AB:
    graph[a].append(b)
    graph[b].append(a)

s1 = [1]
s2 = [N]
fennec = 0
snuke = 0
fixed = np.zeros(N + 1, dtype=bool)
while s1 or s2:
    u1 = []
    for v in s1:
        if fixed[v]:
            continue
        fixed[v] = True
        fennec += 1
        u1.extend(graph[v])
    s1 = u1

    u2 = []
    for v in s2:
        if fixed[v]:
            continue
        fixed[v] = True
        snuke += 1
        u2.extend(graph[v])
    s2 = u2

if fennec > snuke:
    print('Fennec')
else:
    print('Snuke')

Buggy python submission (verdict: Time Limit Exceeded):
import sys

import numpy as np

sys.setrecursionlimit(2 ** 31 - 1)
INF = float('inf')

N = int(sys.stdin.readline())
AB = [list(map(int, sys.stdin.readline().split())) for _ in range(N - 1)]

graph = [set() for _ in range(N + 1)]
for a, b in AB:
    graph[a].add(b)
    graph[b].add(a)


def dfs(to, path):
    if path[-1] == to:
        return path
    v = path[-1]
    prev = path[-2] if len(path) >= 2 else None

    ret = None
    for u in graph[v]:
        if u != prev:
            ret = ret or dfs(to, path + [u])
    return ret


# 1 から N までのパス
path = dfs(N, [1])
cut = (len(path) - 1) // 2
fennec = path[:cut + 1]
snuke = path[cut + 1:]

fixed = np.zeros(N + 1, dtype=str)
fixed[fennec] = 'f'
fixed[snuke] = 's'

while fennec:
    v = fennec.pop()
    for u in graph[v]:
        if not fixed[u]:
            fixed[u] = 'f'
            fennec.append(u)
while snuke:
    v = snuke.pop()
    for u in graph[v]:
        if not fixed[u]:
            fixed[u] = 's'
            snuke.append(u)

if sum(fixed == 'f') > sum(fixed == 's'):
    print('Fennec')
else:
    print('Snuke')


Fixed submission:
import sys

import numpy as np

sys.setrecursionlimit(2 ** 31 - 1)
INF = float('inf')

N = int(sys.stdin.readline())
AB = [list(map(int, sys.stdin.readline().split())) for _ in range(N - 1)]

graph = [[] for _ in range(N + 1)]
for a, b in AB:
    graph[a].append(b)
    graph[b].append(a)

s1 = [1]
s2 = [N]
fennec = 0
snuke = 0
fixed = np.zeros(N + 1, dtype=bool)
while s1 or s2:
    u1 = []
    for v in s1:
        if fixed[v]:
            continue
        fixed[v] = True
        fennec += 1
        u1.extend(graph[v])
    s1 = u1

    u2 = []
    for v in s2:
        if fixed[v]:
            continue
        fixed[v] = True
        snuke += 1
        u2.extend(graph[v])
    s2 = u2

if fennec > snuke:
    print('Fennec')
else:
    print('Snuke')

Buggy python submission (verdict: Time Limit Exceeded):
import sys


class UnionFind:
    def __init__(self, size=None, nodes=None):
        """
        size か nodes どっちか指定。
        nodes は set、size は list を使う。
        set の最悪計算量は O(N) なので size 指定のほうが若干速い
        :param int size:
        :param collections.Iterable nodes:
        """
        assert size is not None or nodes is not None
        if size is not None:
            self._parents = [i for i in range(size)]
            self._ranks = [0 for _ in range(size)]
            self._sizes = [1 for _ in range(size)]
        else:
            self._parents = {k: k for k in nodes}
            self._ranks = {k: 0 for k in nodes}
            self._sizes = {k: 1 for k in nodes}

    def unite(self, x, y):
        """
        x が属する木と y が属する木を併合
        :param x:
        :param y:
        :return:
        """
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return

        # rank が小さい方が下
        if self._ranks[x] > self._ranks[y]:
            # x が root
            self._parents[y] = x
            self._sizes[x] += self._sizes[y]
        else:
            # y が root
            self._parents[x] = y
            self._sizes[y] += self._sizes[x]
            if self._ranks[x] == self._ranks[y]:
                self._ranks[y] += 1

    def find(self, x):
        """
        x が属する木の root
        :param x:
        :return:
        """
        if self._parents[x] == x:
            return x
        self._parents[x] = self.find(self._parents[x])
        return self._parents[x]

    def size(self, x):
        """
        x が属する木のノード数
        :param x:
        :return:
        """
        return self._sizes[self.find(x)]


sys.setrecursionlimit(2 ** 31 - 1)
INF = float('inf')

N = int(sys.stdin.readline())
AB = [list(map(int, sys.stdin.readline().split())) for _ in range(N - 1)]

graph = [set() for _ in range(N + 1)]
for a, b in AB:
    graph[a].add(b)
    graph[b].add(a)


def dfs(to, path):
    if path[-1] == to:
        return path
    v = path[-1]
    prev = path[-2] if len(path) >= 2 else None

    ret = None
    for u in graph[v]:
        if u != prev:
            ret = ret or dfs(to, path + [u])
    return ret


# 1 から N までのパス
path = dfs(N, [1])
cut = (len(path) - 1) // 2
fennec = path[cut]
snuke = path[cut + 1]

uf = UnionFind(size=N + 1)
for a, b in AB:
    if sorted([a, b]) != sorted([fennec, snuke]):
        uf.unite(a, b)

if uf.size(fennec) > uf.size(snuke):
    print('Fennec')
else:
    print('Snuke')


Fixed submission:
import sys

import numpy as np

sys.setrecursionlimit(2 ** 31 - 1)
INF = float('inf')

N = int(sys.stdin.readline())
AB = [list(map(int, sys.stdin.readline().split())) for _ in range(N - 1)]

graph = [[] for _ in range(N + 1)]
for a, b in AB:
    graph[a].append(b)
    graph[b].append(a)

s1 = [1]
s2 = [N]
fennec = 0
snuke = 0
fixed = np.zeros(N + 1, dtype=bool)
while s1 or s2:
    u1 = []
    for v in s1:
        if fixed[v]:
            continue
        fixed[v] = True
        fennec += 1
        u1.extend(graph[v])
    s1 = u1

    u2 = []
    for v in s2:
        if fixed[v]:
            continue
        fixed[v] = True
        snuke += 1
        u2.extend(graph[v])
    s2 = u2

if fennec > snuke:
    print('Fennec')
else:
    print('Snuke')

Buggy python submission (verdict: Time Limit Exceeded):
import sys


class UnionFind:
    def __init__(self, size=None, nodes=None):
        """
        size か nodes どっちか指定。
        nodes は set、size は list を使う。
        set の最悪計算量は O(N) なので size 指定のほうが若干速い
        :param int size:
        :param collections.Iterable nodes:
        """
        assert size is not None or nodes is not None
        if size is not None:
            self._parents = [i for i in range(size)]
            self._ranks = [0 for _ in range(size)]
            self._sizes = [1 for _ in range(size)]
        else:
            self._parents = {k: k for k in nodes}
            self._ranks = {k: 0 for k in nodes}
            self._sizes = {k: 1 for k in nodes}

    def unite(self, x, y):
        """
        x が属する木と y が属する木を併合
        :param x:
        :param y:
        :return:
        """
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return

        # rank が小さい方が下
        if self._ranks[x] > self._ranks[y]:
            # x が root
            self._parents[y] = x
            self._sizes[x] += self._sizes[y]
        else:
            # y が root
            self._parents[x] = y
            self._sizes[y] += self._sizes[x]
            if self._ranks[x] == self._ranks[y]:
                self._ranks[y] += 1

    def find(self, x):
        """
        x が属する木の root
        :param x:
        :return:
        """
        if self._parents[x] == x:
            return x
        self._parents[x] = self.find(self._parents[x])
        return self._parents[x]

    def size(self, x):
        """
        x が属する木のノード数
        :param x:
        :return:
        """
        return self._sizes[self.find(x)]


sys.setrecursionlimit(2 ** 31 - 1)
INF = float('inf')

N = int(sys.stdin.readline())
AB = [list(map(int, sys.stdin.readline().split())) for _ in range(N - 1)]

graph = [set() for _ in range(N + 1)]
for a, b in AB:
    graph[a].add(b)
    graph[b].add(a)


def dfs(to, path):
    if path[-1] == to:
        return path
    v = path[-1]
    prev = path[-2] if len(path) >= 2 else None

    ret = None
    for u in graph[v]:
        if u != prev:
            ret = ret or dfs(to, path + [u])
    return ret


# 1 から N までのパス
path = dfs(N, [1])
cut = (len(path) - 1) // 2
fennec = path[cut]
snuke = path[cut + 1]

uf = UnionFind(size=N + 1)
for a, b in AB:
    if sorted([a, b]) != sorted([fennec, snuke]):
        uf.unite(a, b)

if uf.size(fennec) > uf.size(snuke):
    print('Fennec')
else:
    print('Snuke')


Fixed submission:
import sys

import numpy as np

sys.setrecursionlimit(2 ** 31 - 1)
INF = float('inf')

N = int(sys.stdin.readline())
AB = [list(map(int, sys.stdin.readline().split())) for _ in range(N - 1)]

graph = [[] for _ in range(N + 1)]
for a, b in AB:
    graph[a].append(b)
    graph[b].append(a)

s1 = [1]
s2 = [N]
fennec = 0
snuke = 0
fixed = np.zeros(N + 1, dtype=bool)
while s1 or s2:
    u1 = []
    for v in s1:
        if fixed[v]:
            continue
        fixed[v] = True
        fennec += 1
        u1.extend(graph[v])
    s1 = u1

    u2 = []
    for v in s2:
        if fixed[v]:
            continue
        fixed[v] = True
        snuke += 1
        u2.extend(graph[v])
    s2 = u2

if fennec > snuke:
    print('Fennec')
else:
    print('Snuke')