// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

#define rep(i,n) for(int i=0; i<n; i++)

#define REP(i,m,n) for(ll i=(ll)(m);i<(ll)(n);i++)

long long mo = 1e9 + 7;

typedef long long ll;

typedef long double ld;

typedef pair<int,int> Pii;

typedef pair<ll,ll> Pll;

template<class T, class S> void cmin(T &a, const S &b) { if (a > b)a = b; }

template<class T, class S> void cmax(T &a, const S &b) { if (a < b)a = b; }

template<class A>void PR(A a,ll n){rep(i,n){if(i)cout<<' ';cout<<a[i];}cout << "\n";}

ld PI=3.14159265358979323846;



vector<vector<ll>> G(100010);

vector<ll> memo(100010,-1), memo2(100010);

/*

bool dfs(ll v){

    for(auto& u:G[v]){

        if(memo[u] != 0) continue;

        memo[u] = (co==1?2:1);

        dfs(u,(co==1?2:1));

    }

    return false;

}*/

ll dfs(ll v){

    for(auto& u:G[v]){

        if(memo[u] != -1) continue;

        memo[u] = v;

        dfs(u);

    }

    return 0;

}



struct UnionFind {

    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

    vector<int> size;

    UnionFind(int N): par(N),size(N) {



         //最初は全てが根であるとして初期化

        for(int i = 0; i < N; i++){

            par[i] = i;

            size[i] = -1;

        }

            

    }

    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}

        if (par[x] == x) return x;

        return par[x] = root(par[x]);

    }



    void unite(int x, int y) { // xとyの木を併合

        int rx = root(x); //xの根をrx

        int ry = root(y); //yの根をry

        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま

        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける

        size[ry] += size[rx];

    }



    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す

        int rx = root(x);

        int ry = root(y);

        return rx == ry;

    }

    int getsize(int x){

        return -size[root(x)];

    }

    int getNunion(){//これちょっと遅い sameと組み合わせて順次数えていけば早くなりそう。

        map<int,int> m;

        rep(i,par.size()){

            m[this->root(i)]++;

        }

        return int(m.size());

    }

};



int main(){

    ll N;

    cin >> N;

    ll a,b;

    vector<ll> A(N),B(N);

    rep(i,N-1){

        cin >> a >> b;

        a--;b--;

        G[a].push_back(b);

        G[b].push_back(a);

        A[i] = a;

        B[i] = b;

    }

    a = 0;

    b = N-1;

    memo[a] = -2;

    dfs(a);

    ll t = b;

    ll cnt = 0;

    while(t!=a){

        t = memo[t];

        cnt++;

    }

    ll ns = (cnt-1)/2;

    ll nf = cnt-1-ns;

    cnt = 0;

    t = b;

    memo2[b]=2;

    Pll key;

    while(t!=a){

        ll init = t;

        t = memo[t];

        cnt++;

        if(cnt <= ns){

            memo2[t] = 2;

        }else{

            if(cnt == ns+1){

                key = Pll(init, t);

            }

            memo2[t] = 1;

        }

    }

    UnionFind tree(N);

    rep(i,N-1){

        if((key.first==A[i] && key.second==B[i])||(key.first==B[i] && key.second==A[i])){

            continue;

        }

        tree.unite(A[i],B[i]);

    }

    //cout << tree.getsize(a) << " " << tree.getsize(b) << endl;

    if(tree.getsize(a) > tree.getsize(b)){

        cout << "Fennec" << endl;

    }else{

        cout << "Snuke" << endl;

    }



    /*

    queue<ll> que;

    que.push(a);

    while(!que.empty()){

        ll v = que.front();

        que.pop();

        if(memo[v] != 0) continue;

        memo[v] = 1;

        for(auto& u:G[v]){

            que.push()

        }

    }

    //memo[0] = 1;

    //memo[N-1] = 2;

    /*

    queue<ll> qf;

    queue<ll> qs;

    qf.push(0);

    qs.push(N-1);

    bool st = true;

    vector<ll> cand(N);

    while((!qf.empty()) && (!qs.empty())){

        if(st){

            ll v = qf.front();

            qf.pop();

            if(memo[v] != 0) continue;

            memo[v] = 1;

            for(auto& u:G[v]){

                qf.push(u);

                cand[u] += 2;

            }

            st = false;

        }else{

            ll v = qs.front();

            qs.pop();

            if(memo[v] != 0) continue;

            memo[v] = 2;

            for(auto& u:G[v]){

                qs.push(u);

                cand[u] += 1;

            }

            st = true;

        }

    }

    cout << (st?"Snuke":"Fennec") << endl;*/

}

// Faster C++ solution for the same problem (measured speedup: 5.4224209672927355x):
#include <bits/stdc++.h>

using namespace std;

#define rep(i,n) for(int i=0; i<n; i++)

#define REP(i,m,n) for(ll i=(ll)(m);i<(ll)(n);i++)

#define fi first

#define se second

long long mo = 1e9 + 7;

typedef long long ll;

typedef long double ld;

typedef pair<int,int> Pii;

typedef pair<ll,ll> Pll;

template<class T, class S> void cmin(T &a, const S &b) { if (a > b)a = b; }

template<class T, class S> void cmax(T &a, const S &b) { if (a < b)a = b; }

template<class A>void PR(A a,ll n){rep(i,n){if(i)cout<<' ';cout<<a[i];}cout << "\n";}

ld PI=3.14159265358979323846;



struct UnionFind {

    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

    vector<int> size;

    UnionFind(int N): par(N),size(N) {



         //最初は全てが根であるとして初期化

        for(int i = 0; i < N; i++){

            par[i] = i;

            size[i] = -1;

        }

            

    }

    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}

        if (par[x] == x) return x;

        return par[x] = root(par[x]);

    }



    void unite(int x, int y) { // xとyの木を併合

        int rx = root(x); //xの根をrx

        int ry = root(y); //yの根をry

        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま

        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける

        size[ry] += size[rx];

    }



    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す

        int rx = root(x);

        int ry = root(y);

        return rx == ry;

    }

    int getsize(int x){

        return -size[root(x)];

    }

    int getNunion(){//これちょっと遅い sameと組み合わせて順次数えていけば早くなりそう。

        map<int,int> m;

        rep(i,par.size()){

            m[this->root(i)]++;

        }

        return int(m.size());

    }

};



int main(){

    ll N;

    cin >> N;

    vector<vector<ll>> G(N);

    ll a, b;

    vector<ll> A(N), B(N);

    rep(i,N-1){

        cin >> a >> b;

        a--;b--;

        A[i] = a;

        B[i] = b;

        G[a].push_back(b);

        G[b].push_back(a);

    }

    queue<ll> que;

    que.push(0);

    vector<ll> dist(N, 1e18), memo(N,-1);

    dist[0] = 0;

    while(!que.empty()){

        ll v = que.front();

        que.pop();

        for(auto& u:G[v]){

            if(dist[u] != 1e18) continue;

            dist[u] = dist[v] + 1;

            memo[u] = v;

            que.push(u);

        }

    }

    ll d = dist[N-1];

    //ll df = (d+1)/2;

    ll ds = (d-1)/2;

    ll id = N-1;

    rep(i,ds){

        id = memo[id];

    }

    UnionFind tr(N);

    rep(i,N-1){

        if(A[i] == id && B[i] == memo[id] || A[i] == memo[id] && B[i] == id){

            continue;

        }

        tr.unite(A[i], B[i]);

    }

    ll nf = tr.getsize(0);

    ll ns = tr.getsize(N-1);

    if(nf == ns){

        cout << "Snuke" << endl;

    }else if(nf > ns){

        cout << "Fennec" << endl;

    }else{

        cout << "Snuke" << endl;

    }

    //memo[id], id;

}