CodeEff/ECCO huggingface dataset:
# Original solution
#MLE注意！0や1のケースに注意

def main():
    import sys
    input = sys.stdin.readline
    sys.setrecursionlimit(10**7)
    from collections import Counter, deque
    #from collections import defaultdict
    from itertools import combinations, permutations, accumulate, groupby, product
    from bisect import bisect_left,bisect_right
    from heapq import heapify, heappop, heappush
    import math
    from math import gcd

    #inf = 10**17
    #mod = 10**9 + 7

    n = int(eval(input()))
    a = list(map(int, input().split()))
    adj = [[] for _ in range(n)] #頂点数, 場合によって変える
    for _ in range(n-1):
        c,b = list(map(int, input().split()))
        adj[c-1].append(b-1)
        adj[b-1].append(c-1)

    # 頂点1も含む
    res = [0]*n
    res[0] = 1

    def dfs(v, par, L):
        for nv in adj[v]:
            temp = L[:]
            if nv == par:
                continue
            if a[nv] > temp[-1]:
                temp.append(a[nv])
            else:
                temp[bisect_left(temp, a[nv])] = a[nv]
            res[nv] = len(temp)
            dfs(nv, v, temp)

    L = [a[0]]
    dfs(0, -1, L)
    for i in range(n):
        print((res[i]))

if __name__ == '__main__':
    main()

# Optimized solution
#MLE注意！0や1のケースに注意

def main():
    import sys
    input = sys.stdin.readline
    sys.setrecursionlimit(10**7)
    from collections import Counter, deque
    #from collections import defaultdict
    from itertools import combinations, permutations, accumulate, groupby, product
    from bisect import bisect_left,bisect_right
    from heapq import heapify, heappop, heappush
    import math
    from math import gcd

    #inf = 10**17
    #mod = 10**9 + 7

    n = int(eval(input()))
    a = list(map(int, input().split()))
    adj = [[] for _ in range(n)] #頂点数, 場合によって変える
    for _ in range(n-1):
        c,b = list(map(int, input().split()))
        adj[c-1].append(b-1)
        adj[b-1].append(c-1)

    # 頂点1も含む
    res = [0]*n
    res[0] = 1

    def dfs(v, par, L):
        if v != 0:
            if a[v] > L[-1]:
                temp = -1
                L.append(a[v])
            else:
                temp = bisect_left(L, a[v])
                pre = L[temp]
                L[temp] = a[v]
        res[v] = len(L)
        for nv in adj[v]:
            if nv == par:
                continue
            dfs(nv, v, L)
        if v != 0:
            if temp == -1:
                L.pop(-1)
            else:
                L[temp] = pre

    L = [a[0]]
    dfs(0, -1, L)
    for i in range(n):
        print((res[i]))

if __name__ == '__main__':
    main()
# Original solution
import bisect
from collections import deque
import copy

N = int(eval(input()))
a_array = list(map(int, input().split()))

node_dic = {}
for _ in range(N - 1):
    u, v = list(map(int, input().split()))
    if u in node_dic:
        node_dic[u].append(v)
    else:
        node_dic[u] = [v]

    if v in node_dic:
        node_dic[v].append(u)
    else:
        node_dic[v] = [u]

# print(node_dic)

use_array = [-1] * N
ans_array = [0] * N

edge_array = deque([(1, [0])])
use_array[0] = 1

while(len(edge_array)):
    edge, arr = edge_array.popleft()
    # print(edge, arr, ans_array)

    insert = bisect.bisect_left(arr, a_array[edge - 1])
    if insert == len(arr):
        arr.append(a_array[edge - 1])
    else:
        arr[insert] = a_array[edge - 1]
    ans_array[edge - 1] = len(arr) - 1
    for next_edge in node_dic[edge]:
        if use_array[next_edge - 1] == -1:
            use_array[next_edge - 1] = 1
            arr_next = copy.deepcopy(arr)
            edge_array.append((next_edge, arr_next))

print(("\n".join(map(str, ans_array))))


# Optimized solution
import sys
import bisect


def dfs(edge):
    insert = bisect.bisect_left(lis_array, a_array[edge - 1])
    old = lis_array[insert]
    lis_array[insert] = a_array[edge - 1]
    ans = bisect.bisect_left(lis_array, INF)
    ans_array[edge - 1] = ans
    for next_edge in node_dic[edge]:
        if use_array[next_edge - 1] == -1:
            use_array[next_edge - 1] = 1
            dfs(next_edge)
    lis_array[insert] = old


sys.setrecursionlimit(10 ** 9)
N = int(eval(input()))
a_array = list(map(int, input().split()))

node_dic = {}
for _ in range(N - 1):
    u, v = list(map(int, input().split()))
    if u in node_dic:
        node_dic[u].append(v)
    else:
        node_dic[u] = [v]

    if v in node_dic:
        node_dic[v].append(u)
    else:
        node_dic[v] = [u]

# print(node_dic)

use_array = [-1] * N
ans_array = [0] * N

INF = 2 * 10 ** 9
lis_array = [INF] * N

use_array[0] = 1
dfs(1)
print(("\n".join(map(str, ans_array))))
# Original solution
import sys
sys.setrecursionlimit(10 ** 7)

from bisect import bisect_left

n = int(input())
a = list(map(int, input().split()))
uv = [list(map(int, input().split())) for _ in range(n - 1)]

adj = [[] for _ in range(n)]
for u, v in uv:
    u -= 1
    v -= 1
    adj[u].append(v)
    adj[v].append(u)

arrived = [False] * n

ans = [None] * n
ans[0] = 1


def dfs(u, dp, l):
    arrived[u] = True
    for v in adj[u]:
        if not arrived[v]:
            idx = bisect_left(dp, a[v])
            if idx == l:
                dp_nxt = dp + [a[v]]
                ans[v] = l + 1
                dfs(v, dp_nxt, l + 1)
            else:
                dp_nxt = dp[:idx] + [min(a[v], dp[idx])] + dp[idx+1:]
                ans[v] = l
                dfs(v, dp_nxt, l)


dfs(0, [a[0]], 1)
print(*ans, sep="\n")



# Optimized solution
import sys
sys.setrecursionlimit(10 ** 7)

from bisect import bisect_left

n = int(input())
a = list(map(int, input().split()))
uv = [list(map(int, input().split())) for _ in range(n - 1)]

INF = 10 ** 10

adj = [[] for _ in range(n)]
for u, v in uv:
    u -= 1
    v -= 1
    adj[u].append(v)
    adj[v].append(u)

arrived = [False] * n

ans = [None] * n
ans[0] = 1

dp = [INF] * n


def dfs(u):
    arrived[u] = True
    for v in adj[u]:
        if not arrived[v]:
            idx = bisect_left(dp, a[v])
            tmp = dp[idx]
            dp[idx] = a[v]
            ans[v] = bisect_left(dp, INF - 1)
            dfs(v)
            dp[idx] = tmp


dp[0] = a[0]
dfs(0)
print(*ans, sep="\n")
# Original solution
import bisect
import sys
sys.setrecursionlimit(10**9)

N = int(input())
A = list(map(int, input().split()))

tree = [[] for i in range(N)]
for i in range(N-1):
  u, v = map(int, input().split())
  tree[u-1].append(v-1); tree[v-1].append(u-1)


ans = [0] * N
ans[0] = 1
INF = 10**10
dp = [INF] * N
dp[0] = A[0]
stack = []
def dfs(node, par):
  global ans
  global dp
  global stack
  children = tree[node]
  for child in children:
    if child == par:
      continue
    num = A[child]
    idx = bisect.bisect_left(dp, num)
    stack.append([idx, dp[idx]])
    dp[idx] = num
    ans[child] = bisect.bisect_left(dp, INF)
    dfs(child, node)
    # 巻き戻し
    idx, num = stack.pop()
    dp[idx] = num

dfs(0, -1)
print(*ans, sep='\n')


# Optimized solution
import bisect
import sys
sys.setrecursionlimit(10**9)

N = int(input())
A = list(map(int, input().split()))

tree = [[] for i in range(N)]
for i in range(N-1):
  u, v = map(int, input().split())
  tree[u-1].append(v-1); tree[v-1].append(u-1)


ans = [0] * N
ans[0] = 1
INF = 10**10
dp = [INF] * N
dp[0] = A[0]
stack = []
def dfs(node, par, n):
  global ans
  global dp
  global stack
  children = tree[node]
  for child in children:
    if child == par:
      continue
    num = A[child]
    idx = bisect.bisect_left(dp, num)
    stack.append([idx, dp[idx]])
    dp[idx] = num
    ans[child] = max(n, idx+1)
    # ans[child] = bisect.bisect_left(dp, INF)
    dfs(child, node, max(n, idx+1))
    # 巻き戻し
    idx, num = stack.pop()
    dp[idx] = num

dfs(0, -1, 1)
print(*ans, sep='\n')
# Original solution
import bisect
import sys
sys.setrecursionlimit(10**9)

N = int(input())
A = list(map(int, input().split()))

tree = [[] for i in range(N)]
for i in range(N-1):
  u, v = map(int, input().split())
  tree[u-1].append(v-1); tree[v-1].append(u-1)


ans = [0] * N
ans[0] = 1
INF = 10**10
dp = [INF] * N
dp[0] = A[0]
stack = []
n_stack = []
def dfs(node, par, n):
  global ans
  global dp
  global stack
  children = tree[node]
  for child in children:
    if child == par:
      continue
    num = A[child]
    idx = bisect.bisect_left(dp, num)
    stack.append([idx, dp[idx]])
    n_stack.append(n)
    dp[idx] = num
    n = max(n, idx + 1)
    ans[child] = n
    dfs(child, node, n)
    # 巻き戻し
    idx, num = stack.pop()
    dp[idx] = num
    n = n_stack.pop()

dfs(0, -1, 1)
print(*ans, sep='\n')


# Optimized solution
import bisect
import sys
sys.setrecursionlimit(10**9)

N = int(input())
A = list(map(int, input().split()))

tree = [[] for i in range(N)]
for i in range(N-1):
  u, v = map(int, input().split())
  tree[u-1].append(v-1); tree[v-1].append(u-1)


ans = [0] * N
ans[0] = 1
INF = 10**10
dp = [INF] * N
dp[0] = A[0]
def dfs(node, par, n):
  global ans
  global dp
  children = tree[node]
  for child in children:
    if child == par:
      continue
    num = A[child]
    idx = bisect.bisect_left(dp, num)
    _idx, _num = idx, dp[idx] # 巻き戻し用に退避
    dp[idx] = num
    _n = max(n, idx + 1)
    ans[child] = _n
    dfs(child, node, _n)
    # 巻き戻し
    dp[_idx] = _num

dfs(0, -1, 1)
print(*ans, sep='\n')
# Original solution
import sys, bisect, copy
from collections import deque
input = sys.stdin.readline
sys.setrecursionlimit(10**8)

def main():
    n = int(eval(input()))
    a = list(map(int,input().split()))
    g = [[] for _ in range(n)]
    for _ in range(n-1):
        p,q = list(map(int,input().split()))
        p -= 1
        q -= 1
        g[p].append(q)
        g[q].append(p)
    dis = [10**10]*n
    dis[0] = 0
    que = deque()
    que.append(0)
    pr = [0 for _ in range(n)]
    pr[0] = 1
    ans = ['' for _ in range(n)]
    ans[0] = [a[0]]
    while que:
        go = que.pop()
        for i in range(len(g[go])):
            if dis[g[go][i]] <= dis[go] + 1:
                continue
            lis = copy.copy(ans[go])
            if a[g[go][i]] > lis[-1]:
                lis.append(a[g[go][i]])
            else:
                lis[bisect.bisect_left(lis,a[g[go][i]])] = a[g[go][i]]
            ans[g[go][i]] = lis
            dis[g[go][i]] = dis[go] + 1
            que.append(g[go][i])
    for i in range(n):
        print((len(ans[i])))
    
if __name__ == "__main__":
    main()

# Optimized solution
import sys, bisect, copy
from collections import deque
input = sys.stdin.readline
sys.setrecursionlimit(10**8)
 
def main():
    n = int(eval(input()))
    a = list(map(int,input().split()))
    g = [[] for _ in range(n)]
    for _ in range(n-1):
        p,q = list(map(int,input().split()))
        p -= 1
        q -= 1
        g[p].append(q)
        g[q].append(p)
    dis = [10**10]*n
    dis[0] = 0
    que = deque()
    que.append(0)
    pr = [0 for _ in range(n)]
    pr[0] = 1
    ans = ['' for _ in range(n)]
    ans[0] = [a[0]]
    while que:
        go = que.pop()
        for i in range(len(g[go])):
            if dis[g[go][i]] <= dis[go] + 1:
                continue
            lis = [0 for _ in range(len(ans[go]))]
            for j in range(len(ans[go])):
                lis[j] = ans[go][j]
            if a[g[go][i]] > lis[-1]:
                lis.append(a[g[go][i]])
            else:
                lis[bisect.bisect_left(lis,a[g[go][i]])] = a[g[go][i]]
            ans[g[go][i]] = lis
            dis[g[go][i]] = dis[go] + 1
            que.append(g[go][i])
    for i in range(n):
        print((len(ans[i])))
    
if __name__ == "__main__":
    main()
# Original solution
import bisect
import sys
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10 ** 7)

N = int(input())
A = tuple(map(int, input().split()))
edge = [[] for _ in range(N + 1)]
for _ in range(N - 1):
    x, y = map(int, input().split())
    edge[x].append(y)
    edge[y].append(x)

ans = [-1] * (N + 1)


def DFS(s, LIS, parent=-1):
    a = A[s - 1]
    if not LIS or a > LIS[-1]:
        LIS.append(a)
    else:
        i = bisect.bisect_left(LIS, a)
        LIS[i] = a
    ans[s] = len(LIS)
    for t in edge[s]:
        if t == parent:
            continue
        DFS(t, LIS[:], s)
    return


DFS(1, [])
print(*ans[1:], sep="\n")


# Optimized solution
import bisect
import sys
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10 ** 7)

N = int(input())
A = tuple(map(int, input().split()))
edge = [[] for _ in range(N + 1)]
for _ in range(N - 1):
    x, y = map(int, input().split())
    edge[x].append(y)
    edge[y].append(x)

ans = [-1] * (N + 1)
inf = 10**18
LIS = [inf] * (N + 10)


def DFS(s, parent=0):
    a = A[s - 1]
    i = bisect.bisect_left(LIS, a)
    v = LIS[i]
    LIS[i] = a
    ans[s] = bisect.bisect_left(LIS, inf)
    for t in edge[s]:
        if t == parent:
            continue
        DFS(t, s)
    # 頂点sでの結果をもとに戻す
    LIS[i] = v
    return


DFS(1)
print(*ans[1:], sep="\n")
# Original solution
import sys

from itertools import combinations


def solve(n, pairs):
    survivors = {v: {v} for v in range(1, n + 1)}
    for x, y in reversed(pairs):
        for v, srv in list(survivors.copy().items()):
            if x in srv:
                if y in srv:
                    del survivors[v]
                else:
                    srv.add(y)
            elif y in srv:
                srv.add(x)
    return sum(su.isdisjoint(sv) for su, sv in combinations(list(survivors.values()), 2))


n, m = list(map(int, input().split()))
pairs = []
for line in sys.stdin.readlines():
    x, y = list(map(int, line.split()))
    pairs.append((x, y))
print((solve(n, pairs)))


# Optimized solution
import sys

from itertools import combinations


def solve(n, pairs):
    survivors = {v: {v} for v in range(1, n + 1)}
    for x, y in reversed(pairs):
        for v, srv in list(survivors.copy().items()):
            if x in srv:
                if y in srv:
                    del survivors[v]
                else:
                    srv.add(y)
            elif y in srv:
                srv.add(x)
    return sum(su.isdisjoint(sv) for su, sv in combinations(list(survivors.values()), 2))


n, m = list(map(int, input().split()))
pairs = [tuple(map(int, line.split())) for line in sys.stdin.readlines()]
print((solve(n, pairs)))
# Original solution
ring = input() * 2
word = input()

if ring.find(word) != -1:
    print("Yes")
else:
    print("No")

# Optimized solution
ring = input() * 2
word = input()

if word in ring:
    print("Yes")
else:
    print("No")
# Original solution
s=input()
target=input()
ring=s*2
f=0

for i in range(len(s)):
	if ring[i:i+len(target)]==target:
		f=1
		break
if f==1:
	print("Yes")
else:
	print("No")

# Optimized solution
s=input()
target=input()
ring=s*2

ans="No"
for i in range(len(s)):
	if ring[i:i+len(target)]==target:
		ans="Yes"
		break
print(ans)
# Original solution
a = input()
b = input()
a = a+a
if 0 < a.count(b):
    print('Yes')
else:
    print('No')

# Optimized solution
a = input()
b = input()
a = a+a
if 0 <= a.find(b):
    print('Yes')
else:
    print('No')
# Original solution
from collections import deque

N = int(eval(input()))
M = N - 1
graph = [[] for _ in range(N + 1)]
dis_f = []
dis_s = []
#フェネックの距離
for i in range(M):
    a,b = list(map(int,input().rstrip().split(" ")))
    graph[a].append(b)
    graph[b].append(a)

dist = [-1] * (N + 1)
dist[0] = 0
dist[1] = 0
d = deque()
d.append(1)
while(d):
    v = d.popleft()
    for i in graph[v]:
        if dist[i] != -1:
            continue
        dist[i] = dist[v] + 1
        d.append(i)
    ans_f = dist[1:]
    
#すぬけくんの距離

dist = [-1] * (N + 1)
dist[0] = 0
dist[N] = 0
d = deque()
d.append(N)
while(d):
    v = d.popleft()
    for i in graph[v]:
        if dist[i] != -1:
            continue
        dist[i] = dist[v] + 1
        d.append(i)
    ans_s = dist[1:]

count_f = 0
count_s = 0
for i in range(N):
    if(ans_f[i] <= ans_s[i]):
        count_f += 1
    else:
        count_s += 1
if(count_f > count_s):
    print("Fennec")
else:
    print("Snuke")

# Optimized solution
from collections import deque

N = int(eval(input()))
M = N - 1
graph = [[] for _ in range(N + 1)]
dis_f = []
dis_s = []
#フェネックの距離
for i in range(M):
    a,b = list(map(int,input().rstrip().split(" ")))
    graph[a].append(b)
    graph[b].append(a)

dist_f = [-1] * (N + 1)
dist_f[0] = 0
dist_f[1] = 0
d = deque()
d.append(1)
left = N -1
while(d):
    v = d.popleft()
    for i in graph[v]:
        if dist_f[i] != -1:
            continue
        dist_f[i] = dist_f[v] + 1
        d.append(i)
    
#すぬけくんの距離

dist = [-1] * (N + 1)
dist[0] = 0
dist[N] = 0
d = deque()
d.append(N)
while(d):
    v = d.popleft()
    for i in graph[v]:
        if dist[i] != -1:
            continue
        dist[i] = dist[v] + 1
        d.append(i)

count_f = 0
count_s = 0
for i in range(N):
    if(dist_f[i + 1] <= dist[i + 1]):
        count_f += 1
    else:
        count_s += 1
if(count_f > count_s):
    print("Fennec")
else:
    print("Snuke")
# Original solution
def bfs(v):
  distance=[-1]*n
  distance[v]=0
  next=connection[v]
  next2=set()
  visited=[-1]*n
  visited[v]=1
  visitct=1
  ct=0
  while visitct!=n:
    ct+=1
    for i in range(len(next)):
      distance[next[i]]=ct
      visited[next[i]]=1
      visitct+=1
      for j in range(len(connection[next[i]])):
        if visited[connection[next[i]][j]]==-1:
          next2.add(connection[next[i]][j])
    next=list(next2)
    next2=set()
    
  return distance

import sys
input = sys.stdin.readline
n=int(eval(input()))
l=[list(map(int,input().split())) for i in range(n-1)]
connection=[[] for i in range(n)]
for i in range(n-1):
  connection[l[i][0]-1].append(l[i][1]-1)
  connection[l[i][1]-1].append(l[i][0]-1)

f=bfs(0);s=bfs(n-1)
ctf=0;cts=0
for i in range(n):
  if f[i]<=s[i]:
    ctf+=1
  else:
    cts+=1

if ctf>cts:
  print('Fennec')
else:
  print('Snuke')

# Optimized solution
def bfs(v):
  distance=[-1]*n
  distance[v]=0
  next=connection[v]
  next2=set()
  visited=[-1]*n
  visited[v]=1
  visitct=1
  ct=0
  while len(next)!=0 or visitct!=n:
    ct+=1
    for i in range(len(next)):
      distance[next[i]]=ct
      visited[next[i]]=1
      visitct+=1
      for j in range(len(connection[next[i]])):
        if visited[connection[next[i]][j]]==-1:
          next2.add(connection[next[i]][j])
    next=list(next2)
    next2=set()
  return distance

import sys
input = sys.stdin.readline
n=int(eval(input()))
l=[list(map(int,input().split())) for i in range(n-1)]
connection=[[] for i in range(n)]
for i in range(n-1):
  connection[l[i][0]-1].append(l[i][1]-1)
  connection[l[i][1]-1].append(l[i][0]-1)
 
f=bfs(0);s=bfs(n-1)
ctf=0;cts=0
for i in range(n):
  if f[i]<=s[i]:
    ctf+=1
  else:
    cts+=1
 
if ctf>cts:
  print('Fennec')
else:
  print('Snuke')
# Original solution
import sys
sys.setrecursionlimit(10**6)

n = int(eval(input()))
e = [[] for _ in range(n)]

for i in range(n-1):
    a, b = [int(item) for item in input().split()]
    e[a-1].append(b-1)
    e[b-1].append(a-1)

shortest = []
def get_path(start, end, par, path):
    global shortest
    if end in e[start]:
        shortest = path + [end]
        return True
    for item in e[start]:
        if item != par:
             if get_path(item, end, start, path + [item]):
                 return True

def tree_count(start, par, a, b):
    count = 0
    for item in e[start]:
        if start == a and item == b:
            continue
        if start == b and item == a:
            continue
        if item != par:
            count += 1
            count += tree_count(item, start, a, b)
    return count

get_path(0, n-1, -1, [0])
cut_l = (len(shortest)-1) // 2
p = tree_count(0, -1, shortest[cut_l], shortest[cut_l+1])
q = n - p - 2 
if p > q:
    print("Fennec")
else:
    print("Snuke")

# Optimized solution
import sys
sys.setrecursionlimit(10**6)

n = int(eval(input()))
e = [[] for _ in range(n)]

for i in range(n-1):
    a, b = [int(item) for item in input().split()]
    e[a-1].append(b-1)
    e[b-1].append(a-1)

shortest = []
def get_path(start, end, par):
    if end in e[start]:
        shortest.append(end)
        return True
    for item in e[start]:
        if item != par:
             if get_path(item, end, start):
                 shortest.append(item)
                 return True

def tree_count(start, par, a, b):
    count = 0
    for item in e[start]:
        if start == a and item == b:
            continue
        if start == b and item == a:
            continue
        if item != par:
            count += 1
            count += tree_count(item, start, a, b)
    return count

get_path(0, n-1, -1)
shortest.append(0)
shortest = shortest[::-1]
cut_l = (len(shortest)-1) // 2
p = tree_count(0, -1, shortest[cut_l], shortest[cut_l+1])
q = n - p - 2 
if p > q:
    print("Fennec")
else:
    print("Snuke")
# Original solution
import heapq
N = int(eval(input()))
T = [[] for i in range(N)]
for i in range(N - 1):
    a, b = list(map(int, input().split()))
    a, b = a - 1, b - 1
    T[a].append([b, 1])
    T[b].append([a, 1])


def dijkstra(x):
    d = [float('inf')] * N
    d[x] = 0
    visited = {x}

    # d, u
    hq = [(0, x)]

    while hq:
        u = heapq.heappop(hq)[1]
        visited.add(u)

        for node, cost in T[u]:
            if (node not in visited) and d[node] > d[u] + cost:
                d[node] = d[u] + cost
                heapq.heappush(hq, (d[u]+cost, node))
    return d


B = dijkstra(0)
W = dijkstra(N - 1)

result = [("B" if b <= w else "W") for b, w in zip(B, W)]
print(("Fennec" if result.count("B") - result.count("W") > 0 else "Snuke"))


# Optimized solution
import sys
sys.setrecursionlimit(10 ** 9)

N = int(eval(input()))
T = [[] for i in range(N)]
for i in range(N - 1):
    a, b = list(map(int, input().split()))
    a, b = a - 1, b - 1
    T[a].append([b, 1])
    T[b].append([a, 1])


def dfs(n):
    dist = [-1] * N
    dist[n] = 0
    stack = [n]

    while stack:
        u = stack.pop()
        for v, c in T[u]:
            if dist[v] < 0:
                dist[v] = dist[u] + 1
                stack.append(v)
    return dist


Black = dfs(0)
White = dfs(N - 1)

Black_get = 0
for b, w in zip(Black, White):
    if b <= w:
        Black_get += 1

if Black_get > N // 2:
    print('Fennec')
else:
    print('Snuke')
# Original solution
# ABC067D - Fennec VS. Snuke (ARC078D)
from collections import deque


def bfs(s: int, d: "List[int]") -> None:
    q = deque([s])
    while q:
        v = q.popleft()
        for u in G[v]:
            if not d[u]:
                q.append(u)
                d[u] = d[v] + 1


def main():
    global G, DB, DW
    N, *E = list(map(int, open(0).read().split()))
    G = [[] for _ in range(N + 1)]
    for i in range(0, (N - 1) * 2, 2):
        v, u = E[i : i + 2]
        G[v] += [u]
        G[u] += [v]
    DB, DW = [0] * (N + 1), [0] * (N + 1)
    bfs(1, DB), bfs(N, DW)
    b, w = 0, 0
    for i, j in zip(DB[1:], DW[1:]):
        if i <= j:
            b += 1
        else:
            w += 1
    flg = b > w
    print(("Fennec" if flg else "Snuke"))


if __name__ == "__main__":
    main()

# Optimized solution
# ARC078D - Fennec VS. Snuke (ABC067D)
from collections import deque


def bfs(s: int, d: "List[int]") -> None:
    q = deque([s])
    while q:
        v = q.popleft()
        for u in G[v]:
            if not d[u]:
                q.append(u)
                d[u] = d[v] + 1


def main():
    global G, DB, DW
    N, *E = list(map(int, open(0).read().split()))
    G = [[] for _ in range(N + 1)]
    for i in range(0, (N - 1) * 2, 2):
        v, u = E[i : i + 2]
        G[v] += [u]
        G[u] += [v]
    # DB, DW: distance from G[i] (black) and G[N] (white)
    DB, DW = [0] * (N + 1), [0] * (N + 1)
    bfs(1, DB), bfs(N, DW)
    b, w = 0, 0
    for i, j in zip(DB[1:], DW[1:]):
        if i <= j:
            b += 1
        else:
            w += 1
    flg = b > w
    print(("Fennec" if flg else "Snuke"))


if __name__ == "__main__":
    main()