中石油 6581 Fennec VS. Snuke

 

 

Fennec and Snuke are playing a board game.
On the board, there are N cells numbered 1 through N, and N−1 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
2≤N≤105
1≤ai,bi≤N
The given graph is a tree.

输入

Input is given from Standard Input in the following format:
N
a1 b1
:
aN−1 bN−1

输出

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

翻译:

Fennec和Snuke正在玩棋盘游戏。
在电路板上,有N个电池编号为1到N,N-1个电路连接两个电池。Cell ai通过第i条道路与Cell bi相邻。通过重复前往相邻的小区,可以从每个其他小区到达每个小区。就图论而言,由细胞和道路形成的图是树。
最初,Cell 1涂成黑色,Cell N涂成白色。其他细胞尚未着色。Fennec(谁先走了)和Snuke(谁走了第二个)交替画了一个无色的细胞。更具体地说,每个玩家在她/她的回合中执行以下动作:
Fennec:选择与黑色单元格相邻的未着色单元格,并将其绘制为黑色。
Snuke:选择与白色单元相邻的无色单元,并将其涂成白色。
当一个玩家不能画一个小区时,玩家会输。当Fennec和Snuke最佳地发挥作用时,确定游戏的胜利者。
这个题很简单 ,但我做了好久,一开始时我开了两个队列,一边存F的,一边存S的,结果wa了,为什么呢,因为它扫的时候是从前往后扫,不能保证每一次都是最优的:下面是错误代码。

 

#include<stdio.h>
#include<queue>
#include<math.h>
#include<time.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
#include<map>
#include<stack>
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(a) a&(-a)
#define PI acos(-1)
#define shortime(a)  std::ios::sync_with_stdio(a);
using  namespace std;
const LL mod=1e9+7;
//long long cmp(node a,node b){ if(a.x==b.x) return a.r>b.r;return a.x>b.x;}
//LL  quick(LL x,LL n){ LL ans=1,temp=x; while(n){if(n%2==1){ ans=(ans*temp)%mod;} n/=2;temp=temp*temp%mod;}return ans;}
int maxn (int a,int b,int c){return max(max(a,b),max(b,c));}
LL min(LL a,LL b) {return a<b?a:b;}
int gcd (int a,int b){return b==0?a:gcd(b,a%b);}
vector<int>a[100040];
queue<int>Q;
int main()
{
    int n,x,y;
    int vis[200005];
    mem(vis,0);
    scanf("%d",&n);
    for(int i=0;i<n-1;i++)
    {
        scanf("%d%d",&x,&y);
        a[x].push_back(y);
        a[y].push_back(x);
    }
    int num1=0,num2=0,flag=1;
    vis[1]=1,vis[n]=2;
    Q.push(1);
    Q.push(n);
    while(!Q.empty())
    {
        int temp;
        temp=Q.front();
        Q.pop();
        for(int i=0;i<a[temp].size();i++)
        {
            if(vis[a[temp][i]]==0)
            {
                Q.push(a[temp][i]);
                vis[a[temp][i]]=vis[temp];
                if(vis[temp]==1) num1++;
                else num2++;
            }
        }
    }
    if(num1>num2)
         printf("Fennec\n");
    else printf("Snuke\n");
    return 0;
}

看博客正解,非常简单,一个队列足以,直接用vis表示在哪个队中,太强了。。。。 

#include<stdio.h>
#include<queue>
#include<math.h>
#include<time.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
#include<map>
#include<stack>
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(a) a&(-a)
#define PI acos(-1)
#define shortime(a)  std::ios::sync_with_stdio(a);
using  namespace std;
const LL mod=1e9+7;
//long long cmp(node a,node b){ if(a.x==b.x) return a.r>b.r;return a.x>b.x;}
//LL  quick(LL x,LL n){ LL ans=1,temp=x; while(n){if(n%2==1){ ans=(ans*temp)%mod;} n/=2;temp=temp*temp%mod;}return ans;}
int maxn (int a,int b,int c){return max(max(a,b),max(b,c));}
LL min(LL a,LL b) {return a<b?a:b;}
int gcd (int a,int b){return b==0?a:gcd(b,a%b);}
vector<int>a[200040];
queue<int>Q,P;
int main()
{
    int n,x,y;
    int vis[200005];
    mem(vis,0);
    scanf("%d",&n);
    for(int i=0;i<n-1;i++)
    {
        scanf("%d%d",&x,&y);
        a[x].push_back(y);
        a[y].push_back(x);
    }
    int num1=0,num2=0,flag=1;
    vis[1]=1,vis[n]=2;
    Q.push(1);
    P.push(n);
    while(1)
    {
        if(Q.empty()&&P.empty()) break;
        int temp;
        if(flag==1&&Q.empty()==0)
        {
            temp=Q.front();

            for(int i=0;i<a[temp].size();i++)
            {
                if(vis[a[temp][i]]==0)
                {
                    Q.push(a[temp][i]);
                    vis[a[temp][i]]=1;num1++;
                }
            }Q.pop();

        }
        else if(P.empty()==0){
            temp=P.front();

            for(int i=0;i<a[temp].size();i++)
            {
                if(vis[a[temp][i]]==0)
                {
                    P.push(a[temp][i]);
                    vis[a[temp][i]]=2; num2++;
                }
            }P.pop();

        }
        flag=-flag;
       // printf(".....%d\n",temp);
    }
    int sm=0,sn=0;
    /*for(i=0;i<n;i++)
    {
        if(vis[i]==1) sm++;
        else if(vis[i]==2) sn++;
    }
    if ()*/
    if(num1>num2)
         printf("Fennec\n");
    else printf("Snuke\n");
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值