AtCoder:Fennec VS. Snuke(dfs & 思维)

来源:互联网 发布:2016网络购彩最新消息 编辑:程序博客网 时间:2024/05/22 16:39

D - Fennec VS. Snuke


Time limit : 2sec / Memory limit : 256MB

Score : 400 points

Problem Statement

Fennec and Snuke are playing a board game.

On the board, there are N cells numbered 1 through N, and N1 roads, each connecting two cells. Cell ai is adjacent to Cell bi through the i-th road. Every cell can be reached from every other cell by repeatedly traveling to an adjacent cell. In terms of graph theory, the graph formed by the cells and the roads is a tree.

Initially, Cell 1 is painted black, and Cell N is painted white. The other cells are not yet colored. Fennec (who goes first) and Snuke (who goes second) alternately paint an uncolored cell. More specifically, each player performs the following action in her/his turn:

  • Fennec: selects an uncolored cell that is adjacent to a black cell, and paints it black.
  • Snuke: selects an uncolored cell that is adjacent to a white cell, and paints it white.

A player loses when she/he cannot paint a cell. Determine the winner of the game when Fennec and Snuke play optimally.

Constraints

  • 2N105
  • 1ai,biN
  • The given graph is a tree.

Input

Input is given from Standard Input in the following format:

Na1 b1:aN1 bN1

Output

If Fennec wins, print Fennec; if Snuke wins, print Snuke.


Sample Input 1

Copy
73 61 23 17 45 71 4

Sample Output 1

Copy
Fennec

For example, if Fennec first paints Cell 2 black, she will win regardless of Snuke's moves.


Sample Input 2

Copy
41 44 22 3

Sample Output 2

Copy
Snuke
题意:一棵树由N个节点,1节点黑色,N节点白色,两个人轮流涂色,先手将黑色节点相邻一个无色节点涂成黑色,后手白色亦然,谁不能涂就输,问谁会赢。

思路:最优策略显然先往对方的路径涂过去,那么计算一下两色相遇时谁的子节点多即可。

# include <bits/stdc++.h>using namespace std;const int maxn = 1e5+3;int cnt=0, id=0, Next[maxn],in[maxn],out[maxn];int fa[maxn][20], len[maxn];struct node{    int v, next;}edge[maxn<<1];void add_edge(int u, int v){    edge[cnt] = {v, Next[u]};    Next[u] = cnt++;    edge[cnt] = {u, Next[v]};    Next[v] = cnt++;} void dfs(int cur, int pre, int d){    fa[cur][0] = pre;    len[cur] = d;    for(int i=1; i<20; ++i)        fa[cur][i] = fa[fa[cur][i-1]][i-1];    in[cur] = ++id;    for(int i=Next[cur]; i!=-1; i=edge[i].next)    {        int v = edge[i].v;        if(v == pre) continue;        dfs(v, cur, d+1);    }    out[cur] = id;}int main(){    int n, a, b;    scanf("%d",&n);    memset(Next, -1, sizeof(Next));    for(int i=1; i<n; ++i)    {        scanf("%d%d",&a,&b);        add_edge(a, b);    }    dfs(1, 0, 0);    int tmp=(len[n]-1)/2, now=n;    for(int i=0; i<20; ++i)        if(tmp>>i&1) now = fa[now][i];    int bl = n-(out[now]-in[now]+1)-len[n]/2-1;    int wh = out[now]-in[now]+1-tmp-1;    if(len[n]&1)    {        if(bl <= wh) puts("Snuke");        else puts("Fennec");    }    else    {        if(wh <= bl) puts("Fennec");        else puts("Snuke");    }    return 0;}