题意中的操作是:
每个”子”节点 -1,自己 +1
用maxc[u]维护u能够为其上面的祖先节点提供的最大增加值。
最终答案就是a[1] + min(maxc[u])
maxc[u]求法:
以u为根节点,其子节点j的maxc[j]的最小值是minv
1. a[u] >= minv, 则minc[u] = minv | u为上面节点的贡献能力被其子节点限制了
2. a[u] < minv, 则minc[u] = (a[u] + minv) / 2 | 在u点执行minv / 2次操作,最大限度提高自己为上面节点的贡献值
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include "bits/stdc++.h"
using namespace std;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define fios ofstream("testx.txt");cout.rdbuf(out.rdbuf())
#define endl "\n"
#define INF 0x3f3f3f3f
#define MINF 2147483647
#define eps 1e-6
#define PI acos(-1)
#define lowbit(x) (x & (-x))
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
#define x first
#define y second
const int N = 200010, M = N * 2;
int n;
int a[N];
int h[N], e[M], ne[M], idx;
int maxc[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u, int fa)
{
int minv = INF;
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
dfs(j, u);
minv = min(minv, maxc[j]);
}
if(u == 1) return ;
if(minv == INF) maxc[u] = a[u];
else
{
if(a[u] >= minv) maxc[u] = minv;
else maxc[u] = (a[u] + minv) / 2;
}
return ;
}
int main()
{
int T;
cin >> T;
while(T--)
{
memset(maxc, 0x3f, sizeof maxc);
memset(h, -1, sizeof h);
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 2; i <= n; i++)
{
int t;
cin >> t;
add(t, i), add(i, t);
}
dfs(1, -1);
int res = INF;
for(int i = 2; i <= n; i++) res = min(res, maxc[i]);
if(res == INF) cout << a[1] << endl;
else cout << a[1] + res << endl;
}
return 0;
}