「AGC010F」 Tree Game

「AGC010F」 Tree Game

传送门

切了一个 AGC 的题,很有精神。

于是决定纪念一下。

首先如果任意一个人在点 \(u\),他肯定不会向点权大于等于 \(a_u\) 的点走的,因为此时另一个人的最优策略显然是走回到点 \(u\),然后两个点的权值都减一,这样下去先输的肯定是前者。

然后一个人只会向点权小于 \(a_u\) 的地方走,根据这个性质判断一下:

  • 如果当前这个人在点 \(u\) 没有路可以走,或是与 \(u\) 相连的点的权值均大于 \(a_u\),那么这个人肯定就输了。
  • 如果某个人在点 \(u\),且存在一棵子树使得另一个人必败,那么这个人肯定就赢了。

按照这个东西从每个点出发 \(\text{DFS}\) 一下即可,时间复杂度为 \(O(n^2)\)

而且感觉可能存在优于这个复杂度的解法?

我不会,欢迎大佬教我。

/*---Author:HenryHuang---*/
/*---Never Settle---*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e3+5;
int c[maxn];
vector<int> e[maxn];
int dfs(int u,int f,int now){
	int flag=0;
	for(auto v:e[u]){
		if(v==f) continue;
		if(c[v]>=c[u]) continue;
		int tmp=dfs(v,u,now^1);
		if(now==1&&tmp) return 1;
		else if(now==0&&tmp==0) return 0;
	}
	if(flag==0){
		if(now==1) return 0;
		else return 1;
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;++i) cin>>c[i];
	for(int i=1;i<n;++i){
		int a,b;cin>>a>>b;
		e[a].emplace_back(b);
		e[b].emplace_back(a);
	}
	for(int i=1;i<=n;++i) if(dfs(i,0,1)) cout<<i<<' ';
	return 0;
}
posted @ 2021-03-05 19:10  Henry__Huang  阅读(82)  评论(0编辑  收藏  举报