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.

样例输入

7
3 6
1 2
3 1
7 4
5 7
1 4

样例输出

Fennec

仔细分析这道题的话,会发现最优的策略就是双方沿着1到n的这条路径轮流的涂过去,直到1到n上的点都被涂过,剩下的就是看谁的领域大啦,这样看来好像是用dfs找到1到n的那条路,然后把它们涂上颜色,其实完全可以用bfs在双方往1到n的那条路上轮流涂色的时候,顺便把周围的点一块涂了,因为一旦1到n上的点被涂了之后,和那些点在一个层次(可以把这个图看成一个二叉树,同一个层次,就是相当于在树里距离某点距离相同的点的集合)上的点不可能被对方给涂了,大家画一下图就知道啦,早晚都要涂,这样的话,一个bfs就过啦,最后只需要统计一下各自的点谁多就可以啦,下边是代码

#include<iostream>
#include<vector>
#include<queue>

using namespace std;
const int N=200002;
int main(){
	int color[N]={0};//用来记录颜色的数组

vector<int>ve[N];
queue<int>qu;
int n;
	cin>>n;
	//先对颜色初始化
	color[1]=1;//1代表黑色;
	color[n]=2;//2代表白色;
	int x,y;
	
	for(int i=1;i<n;i++){
	cin>>x>>y;
	//读入数据,把数据读到一个二维的不定数组里面
	ve[x].push_back(y);
	//这个地方之所以要把x和y的次序换一下是因为x与y相连,y同时也与x相连,这样在程序后边用bfs扫描的时候大家就能看懂啦
	ve[y].push_back(x);
	}
	qu.push(1);//由于是先从1点开始,先把1压入队列,然后再压n点
	qu.push(n);
	int aim;
	int sum[3]={0};//用来统计各自涂点的个数的数组
	while(!qu.empty()){
		aim=qu.front();//取出队列中的元素,然后开始下边的bfs
		qu.pop();
		for(int i=0;i<ve[aim].size();i++){
			if(color[ve[aim][i]])//如果这个点不为零,就说明这个点已经被涂过了,就不能再涂啦,直接continue
				continue;
		color[ve[aim][i]]=color[aim];//如果该点没有涂就把他标记成各自的标记(黑1白2)
		qu.push(ve[aim][i]);//然后再把该点压入队列,等待下一次扫描
		sum[color[aim]]++;//统计各自涂点的个数
		}
	}
	if(sum[1]>sum[2])
		cout<<"Fennec"<<endl;
	else
		cout<<"Snuke"<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/u014788620/article/details/81040547