您的位置:首页 > 其它

【JZOJ 5500】【清华集训2017模拟12.10】营养餐

2017-12-15 21:43 211 查看

Description

JM 是 DY 的好朋友。为了感谢 JM 多年来对自己的关心,DY 决定请他吃一顿水果营养餐.

DY 有一棵有 n 个结点的树,结点 1 为根。树上每一个结点都长着许多水果,其中,结点 i 上有 ai 个水果,每个水果重 bi .

水果虽然好吃,但是这棵树非常脆弱! 一旦某结点的子结点上的水果总重量过大,树枝就会承受不住压力而断裂! 所以,随时需要保持任意一个结点 i:

ai<=∑c∈Child(i)ac∗bc

(数据保证初始局面满足该条件).

JM 说, 谢谢你的这些水果, 不过我的内心毫无波动, 甚至还有点想博弈. 我们轮流来操作: 选择一个结点, 摘走若干个水果, 不可以不摘. 不可操作者输.

DY 说, 这毫无意义,我们都足够聪明,这个游戏一旦确定谁为先手,结果也确定了.

然而, 在前排吃瓜的你并不知道游戏的结果,所以,你得编写程序来知道谁会赢.

Solution

显然可以把题目差分,每次去多少个变成每次在父亲上加上多少个,也就是把这么多移到父亲上,

显然b=0的对父亲没影响,断开,

剩下的就是一个阶梯问题了,直接异或奇数层即可,

Code

#include <cstdio>
#include <algorithm>
#include <map>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
const int N=50500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
int a
,b
;
int B[2*N][2],A
,B0;
void link(int q,int w)
{
B[++B0][0]=A[q];A[q]=B0,B[B0][1]=w;
B[++B0][0]=A[w];A[w]=B0,B[B0][1]=q;
}
void dfs(int q,int c,int fa)
{
efo(i,q)if(B[i][1]!=fa)a[q]-=a[B[i][1]]*b[B[i][1]];
if(!b[q])c=1;
if(c&1)ans=ans^a[q];
efo(i,q)if(B[i][1]!=fa)dfs(B[i][1],c+1,q);
}
int main()
{
freopen("meal.in","r",stdin);
freopen("meal.out","w",stdout);
int q,w,_;
for(read(_);_;--_)
{
read(n);
fo(i,1,n)read(a[i]);
fo(i,1,n)read(b[i]),A[i]=0;B0=0;
fo(i,1,n-1)read(q),read(w),link(q,w);
ans=0;
dfs(1,1,0);
if(ans)printf("YES\n");
else printf("NO\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: