列表

详情


NC19799. 树链博弈

描述

给定一棵 n 个点的树,其中 1 号结点是根,每个结点要么是黑色要么是白色
现在小 Bo 和小 Biao 要进行博弈,他们两轮流操作,每次选择一个黑色的结点将它变白,之后可以选择任意多个(可以不选)该点的祖先(不包含自己),然后将这些点的颜色翻转,不能进行操作的人输
由于小 Bo 猜拳经常输给小 Biao,他想在这个游戏上扳回一城,现在他想问你给定了一个初始局面,是先手必胜还是后手必胜

输入描述

第一行一个正整数 n
第二行 n 个整数 w1..wn,wi∈ {0,1},wi=1 表示第 i 个结点一开始是黑点,否则是白点
接下来 n-1 行,每行两个正整数 u,v 表示一条树边 (u,v)

输出描述

如果先手必胜,输出First ,否则输出Second

示例1

输入:

2
1 0
1 2

输出:

First

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 5ms, 内存消耗: 492K, 提交时间: 2018-10-04 13:02:45

#include<bits/stdc++.h>

using namespace std;

int n;
int ans;
int w[1100];
vector<int> g[1100];
void dfs(int x,int fa,int dep)
{
	if (w[x]) ans^=1<<(dep-1);
	for (int i=0;i<g[x].size();i++)
		if (g[x][i]!=fa) dfs(g[x][i],x,dep+1);
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d",&w[i]);
	for (int i=1;i<n;i++)
	{
		int x,y;
		scanf("%d %d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs(1,0,1);
	if (ans) printf("First\n");
	else printf("Second\n");
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 5ms, 内存消耗: 504K, 提交时间: 2020-01-28 17:25:24

#include<bits/stdc++.h>
#define rep(i,s,e) for(int i=s; i<e; ++i)
using namespace std;
int a[1005],ans;
vector<int>vv[1005];
void dfs(int x,int f,int d){
	if(a[x]) ans^=1<<d;
	for(int t:vv[x]) if(t!=f) dfs(t,x,d+1);
}
int main(){
	int n; cin>>n; rep(i,1,n+1) cin>>a[i]; rep(i,1,n){
		int u,v; cin>>u>>v; vv[u].push_back(v); vv[v].push_back(u); 
	} dfs(1,0,0); puts(ans?"First":"Second");
}

上一题