0%

CF767C Garland

传送门

Solution

设所有节点的权重之和为 tottot,若 tottot 不能被 33 整除,则问题无解。

vv 在以 uu 为根的子树中,且以 vv 为根的子树权重和为 n3\dfrac{n}{3},则 fu=vf_u=v。如果有多个符合要求的 vv,则 fuf_u 取任意一个即可。如果 vv 不存在,则 fu=0f_u=0。dp 可求出 fuf_u。当且仅当下面两种情况,问题有解:

  1. vvuu 的儿子,且有两个或以上的 vv 满足 fvf_v 非零。答案为这两个 fvf_v
  2. fuf_u 非零,且以 uu 为根的子树权重和等于 2n3\dfrac{2n}{3}。答案为 uufuf_u

时间复杂度 O(n)O(n)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;

int n, a[N], fa[N], sum[N], f[N], tot;
vector<int> g[N];

void dfs(int u)
{
sum[u] = a[u];
for (int v : g[u]) {
dfs(v);
sum[u] += sum[v];
if (f[v]) {
if (!f[u])
f[u] = f[v];
else {
printf("%d %d", f[u], f[v]);
exit(0);
}
}
}
if (sum[u] == tot * 2 && f[u] && fa[u]) {
printf("%d %d", f[u], u);
exit(0);
}
if (sum[u] == tot)
f[u] = u;
}

int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &fa[i], &a[i]);
g[fa[i]].push_back(i);
tot += a[i];
}
if (tot % 3) {
printf("-1");
return 0;
}
tot /= 3;
dfs(g[0][0]);
printf("-1");
return 0;
}