【博弈】【树形DP】AGC010F Tree Game

7 篇文章 0 订阅

分析:

有点坑的NP状态转移的题。
考虑将最开始的点设为根, f ( x ) f(x) f(x)表示仅在以x为根的子树中的NP状态。
转移就是:
当且仅当 x x x的某个儿子 v v v,满足 f ( v ) = 0 f(v)=0 f(v)=0 a v &lt; a x a_v&lt;a_x av<ax时, f ( x ) = 1 f(x)=1 f(x)=1

证明很简单,如果 f ( v ) = 0 f(v)=0 f(v)=0,那么当前在x这个玩家,肯定想把游戏转移到v的子树中进行。然而对方肯定要抵抗,那么就会在(v,x)之间来回鬼畜,因为 a v &lt; a x a_v&lt;a_x av<ax,所以当 a v a_v av减为1时,这个人就不再敢抵抗了,因为一旦他移动到x,那么下一次对方就再移动到v(然后石子为0个),他就输了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 3010
using namespace std;
int n;
int a[MAXN];
struct node{
	int x;
	node *nxt;	
}edge[MAXN*2];
node *head[MAXN],*ncnt=edge;
int u,v;
void add_edge(int x,int y){
	++ncnt;
	ncnt->x=y;
	ncnt->nxt=head[x];	
	head[x]=ncnt;
}
bool dfs(int x,int fa){
	bool res=0;
	for(node *v=head[x];v!=NULL;v=v->nxt){
		int u=v->x;
		if(u==fa)
			continue;
		if(dfs(u,x)==0&&a[u]<a[x])
			res=1;
	}
	return res;
}
int main(){
	SF("%d",&n);
	for(int i=1;i<=n;i++)
		SF("%d",&a[i]);
	for(int i=1;i<n;i++){
		SF("%d%d",&u,&v);
		add_edge(u,v);
		add_edge(v,u);
	}
	for(int i=1;i<=n;i++)
		if(dfs(i,0))
			PF("%d ",i);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值