JZOJ 5500. 【清华集训2017模拟12.10】营养餐
2017-12-09 17:10
260 查看
题目
JM 是 DY 的好朋友。为了感谢 JM 多年来对自己的关心,DY 决定请他吃一顿水果营养餐.DY 有一棵有 n 个结点的树,结点 1 为根。树上每一个结点都长着许多水果,其中,结点 i 上有 ai 个水果,每个水果重 bi .
水果虽然好吃,但是这棵树非常脆弱! 一旦某结点的子结点上的水果总重量过大,树枝就会承受不住压力而断裂! 所以,随时需要保持任意一个结点 i:
(数据保证初始局面满足该条件).
JM 说, 谢谢你的这些水果, 不过我的内心毫无波动, 甚至还有点想博弈. 我们轮流来操作: 选择一个结点, 摘走若干个水果, 不可以不摘. 不可操作者输.
DY 说, 这毫无意义,我们都足够聪明,这个游戏一旦确定谁为先手,结果也确定了.
然而, 在前排吃瓜的你并不知道游戏的结果,所以,你得编写程序来知道谁会赢.
题解
看一波数据范围。
前两个点显然暴力。然而我不会,GG。
点3,4,b=0,所以a随便取,那么可以看作是n堆石子,每堆ai个的Nim游戏。
直接异或起来看等不等于0即可。
点5,只有根节点到某个点为1的点的那条路径上的点a=1,其他a=0。
点6,设那两个a=1的点标号为x,y,只有根节点到lca(x,y)的点的a=2,lca(x,y) x,y的路径上的点a=1。那么可以发现,如果都剩下a=2的点,那么先手必败。判断lca(x,y) x,y的路径上的点的个数不含lca(x,y)的奇偶性即可。
点7,设numi=ai−Σc∈son[i]ac∗bc,那么每当ai减少k,numi减少k,numfai增加k。
那么介绍一个新的博弈模型,阶梯式Nim。
将奇数深度的点的num的集合为A,偶数深度的点的num的集合为B。根节点深度为1。
如果操作奇数深度的非根节点,那么A中石子移到了B,操作偶数深度的非根节点,那么B中石子移到了A,操作根节点,那么A中石子移走。
所以当必败方将B中的石子移到A中时,对方也可以将移进B中的相同个数的石子移进A。
可以认为B中的石子是没有用的。
那么如果b=0,则i对fai不产生影响,所以i的子树可以看做一棵独立的子树。
无论b为何值,只要是放入B集合的石子都没有用了。
所以计算出森林中深度为奇数的num,异或起来判断是否等于0即可。
心得
①部分分的解法与正解的解法一定有很大出入!!!②一定要找到这样的方法:必败方给出一定的操作,然后对方能够以相同的操作让必败方回到必败态,那么此博弈方案可行。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define N 50005 #define LL long long #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; struct note{ int to,next; };note edge[N*2]; int head ,tot; LL a ,b ,fa ,s ,num ; LL i,j,n,m,_,sum; LL u,v,step; bool p; LL read(){ LL res=0,fh=1;char ch; while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')fh=-1,ch=getchar(); while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar(); return res*fh; } void lb(LL x,LL y){edge[++tot].to=y;edge[tot].next=head[x];head[x]=tot;} void dg(int x){ for(int i=head[x];i;i=edge[i].next) if(fa[x]!=edge[i].to){ fa[edge[i].to]=x; if(b[edge[i].to]==0)s[edge[i].to]=1; else s[edge[i].to]=s[x]^1; dg(edge[i].to); num[x]-=a[edge[i].to]*b[edge[i].to]; } } int main(){ _=read(); while(_--){ tot=0; memset(edge,0,sizeof(edge)); memset(head,0,sizeof(head)); memset(fa,0,sizeof(fa)); memset(s,0,sizeof(s)); n=read(); fo(i,1,n)a[i]=read(),num[i]=a[i]; fo(i,1,n)b[i]=read(); fo(i,1,n-1){ u=read(),v=read(); lb(u,v),lb(v,u); } s[1]=1; dg(1); sum=0; fo(i,1,n)if(s[i])sum^=num[i]; if(sum)printf("YES\n");else printf("NO\n"); } return 0; }
相关文章推荐
- [JZOJ5500]【清华集训2017模拟12.10】营养餐
- 【JZOJ 5500】【清华集训2017模拟12.10】营养餐
- JZOJ5498. 【清华集训2017模拟12.10】大佬的难题
- jzoj5498 【清华集训2017模拟12.10】大佬的难题 巧妙容斥
- [JZOJ5498]【清华集训2017模拟12.10】大佬的难题
- JZOJ 5490. 【清华集训2017模拟11.28】图染色
- 【JZOJ 5276】【清华集训2017模拟】神奇的玩具
- 【JZOJ5296】【清华集训2017模拟】Sequence
- [JZOJ5485]【清华集训2017模拟11.26】字符串
- 【JZOJ 5495】【清华集训2017模拟12.09】MiniumCut(最小割树)
- 【JZOJ 5295】【清华集训2017模拟】Create
- JZOJ 5496. 【清华集训2017模拟12.09】Tree
- JZOJ 5483. 【清华集训2017模拟11.26】简单路径
- 【JZOJ5295】【清华集训2017模拟】Create
- 【JZOJ 5296】【清华集训2017模拟】Sequence
- 【清华集训2017模拟12.10】回文串
- [jzoj]5484. 【清华集训2017模拟11.26】快乐树(树形DP)
- JZOJ 5485. 【清华集训2017模拟11.26】字符串
- 【JZOJ5316】【清华集训2017模拟8.19】merge
- 【清华集训2017模拟12.10】大佬的难题