1388C 1800的题
题意:
一个国家由n个城市组成,并且这些城市之间的道路形成了一棵树,并且首都为1,其他城市为2~n,有m个人在首都打工,要回到自己的家乡,这些人有开心的也有不开心的,开心的人也有可能在回家的路上变为不开心的,现在给你数组p[]表示每个城市是多少个人的家乡,h[]表示有多少人经过这个城市是开心的抑或不开心的,数值为开心的人数减去不开心的人数,注意这里是经过即可,在这个城市驻留的也算,然后给你n-1条边,表示这个国家各个城市之间的道路关系,问你这个开心的数值是否合理。
思路:
对于每个城市来说我们可以记录他的人流量,即有多少个人会经过这个城市或者在这个城市驻留,同时对于每个人的心情可以进行计算假设这个城市为i,那么经过这个城市的人为这个城市i的子树的所有的加起来,同时有h[i]=good[i]-bad[i](开心的人数减去不开心的人数),sum=good[i]+bad[i],(sum表示人流量),通过这两个式子可以得到h[i]+sum=good[i]*2。当然对于这个节点对应的子树要dfs一遍才能得到。之后就是对于一些条件的判断了,例如sum+h[i]=good[i]*2,即表示能被2整除,还有good[i]必须小于当前节点的流量,而且大于子树的开心人数。
代码如下:
ll sum[maxn], h[maxn], p[maxn], good[maxn];
bool flag;
std::vector<ll> v[maxn];
inline void dfs(int pre, int u){
ll s = 0;
sum[u] = p[u];
for(int i = 0; i < v[u].size(); i++){
if(v[u][i]==pre) continue;
dfs(u, v[u][i]);
s += good[v[u][i]];
sum[u] += sum[v[u][i]];
}
if((h[u]+sum[u])%2!=0) flag = 0;
good[u] = (h[u]+sum[u])/2;
if(good[u]>sum[u]) flag = 0;
if(good[u]<s) flag = 0;
}
inline void cf(){
int t;
t = read();
while(t--){
memset(v,0,sizeof(v));
memset(good, 0, sizeof(good));
flag = 1;
int n=read(), m=read();
for(int i = 1; i <= n; i++) p[i]=read();
for(int i = 1; i <= n; i++) h[i]=read();
for(int i = 1; i < n; i++){
int x=read(), y=read();
v[x].push_back(y); v[y].push_back(x);
}
dfs(0, 1);
if(flag) printf("YES\n");
else printf("NO\n");
}
return ;
}
signed main(){
cf();
return 0;
}
还有一种代码,虽然说思想是差不多的
std::vector<int> v[maxn];
int p[maxn], h[maxn];
int flag;
inline void dfs(int x, int pre){
ll sum = 0;
for(int i = 0; i < v[x].size(); i++){
if(v[x][i]!=pre){
dfs(v[x][i], x);
sum += h[v[x][i]]; //当前节点的子树开心的总人数,不包括当前节点
p[x] += p[v[x][i]]; //当前节点的经过的人数,包括住在这个节点的人,也可以称之为流量把
}
}
h[x]+=p[x];
//h[x]/2为当前节点有多少人是以开心的心情经过这个节点的,
//所以要符合必须是2的倍数
//同时h[x]/2必须小于等于当前节点的人流量,这个原因简单,假设所有的人经过这个节点都是开心的h[x]/2的最大值也就只能达到p[x]
//当前节点的开心人数要大于等于其子树的开心人数,因为如果不开心的话不能变为开心
if(h[x]%2!=0) flag = 0;
else if(h[x]>2*p[x]) flag = 0;
else if(h[x]<sum) flag = 0;
}
inline void cf(){
int t;
t = read();
while(t--){
memset(v,0,sizeof(v));
flag = 1;
int n=read(), m=read();
for(int i = 1; i <= n; i++) p[i]=read();
for(int i = 1; i <= n; i++) h[i]=read();
for(int i = 1; i < n; i++){
int x=read(), y=read();
v[x].push_back(y);v[y].push_back(x);
}
dfs(1,0);
if(flag) printf("YES\n");
else printf("NO\n");
}
return ;
}
signed main(){
cf();
return 0;
}