https://codeforces.com/contest/1388/problem/C
题意
给定n个节点的树结构,m个人初始在根节点1号,已知每个人都有各自要到达的节点(默认走最短路),他们刚出发有各自的心情状态(好/坏)且我们未知,在节点之间的转移过程中好心情会转化为坏心情,但心情坏的不会发生改变。先给定每个节点数据h[i],理论上值为该节点上 心情好的人数 - 心情坏的人数,现要判断给定数据是否正确。
思路
设经过城市
u
u
u的好心情人数为:
g
[
u
]
g[u]
g[u],拜访城市
u
u
u的总人数为:
a
[
u
]
a[u]
a[u],城市
u
u
u检测到的最终心情值为
h
[
u
]
h[u]
h[u]
g
[
u
]
g[u]
g[u]可由此推出:
g
[
u
]
−
(
a
[
u
]
−
g
[
u
]
)
=
h
[
u
]
→
g
[
u
]
=
(
a
[
u
]
+
h
[
u
]
)
/
2
g[u]−(a[u]−g[u])=h[u]→g[u]=(a[u]+h[u]) / 2
g[u]−(a[u]−g[u])=h[u]→g[u]=(a[u]+h[u])/2
其中:
- 2 2 2能整除 ( a [ u ] + h [ u ] ) (a[u]+h[u]) (a[u]+h[u])
- g [ u ] ∈ [ 0 , a [ u ] ] g[u]∈[0,a[u]] g[u]∈[0,a[u]] :因为好心情人数不可能超过总人数
- g [ u ] ≥ ∑ v ∈ s o n g [ v ] g[u]≥\displaystyle\sum_{v∈son}g[v] g[u]≥v∈son∑g[v] :父节点的好心情肯定大于等于子节点的好心情总和
用 d f s dfs dfs 从节点 1 1 1 跑一遍树,用变量 s u m sum sum记录子节点的总好心情,结束访问后判断上面三个条件。
代码
#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false) , std::cin.tie(0) , std::cout.tie(0)
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define pb push_back
using namespace std;
const int N = 1e5 + 10;
int n,m,p[N],u,v,flag;
int a[N],h[N],g[N];
vector<int>e[N];
void dfs(int u,int fa)
{
a[u] = p[u];
int sum = 0;
for(auto v:e[u]){
if (v == fa) continue;
dfs(v,u);
sum += g[v];
a[u] += a[v];
}
if ((a[u] + h[u])&1) {flag = 0; return;}
g[u] = (a[u] + h[u]) >> 1;
if (g[u] < 0 || g[u] > a[u]) {flag = 0; return;}
if (sum > g[u]) {flag = 0; return;}
}
signed main()
{
ios;
int T;
cin >> T;
while (T--)
{
cin >> n >> m;
rep(i,1,n) cin >> p[i];
rep(i,1,n) cin >> h[i];
rep(i,1,n-1){
cin >> u >> v;
e[u].pb(v);
e[v].pb(u);
}
flag = 1;
dfs(1,0);
if (flag) puts("YES");
else puts("NO");
rep(i,1,n) e[i].clear();
}
return 0;
}
参考博客:https://blog.csdn.net/weixin_45750972/article/details/107706065