Problem:
Dungeon 2
Bob is playing a game called "Dungeon 2" which is the sequel to the popular "Dungeon" released last year. The game is played on a map consisting of $N$ rooms and $N-1$ roads connecting them. The roads allow bidirectional traffic and the player can start his tour from any room and reach any other room by way of multiple of roads. A point is printed in each of the rooms.
Bob tries to accumulate the highest score by visiting the rooms by cleverly routing his character "Tora-Tora." He can add the point printed in a room to his score only when he reaches the room for the first time. He can also add the points on the starting and ending rooms of Tora-Tora’s journey. The score is reduced by one each time Tora-Tore passes a road. Tora-Tora can start from any room and end his journey in any room.
Given the map information, make a program to work out the maximum possible score Bob can gain.
Input
The input is given in the following format.
$N$
$p_1$
$p_2$
$...$
$p_N$
$s_1$ $t_1$
$s_2$ $t_2$
$...$
$s_{N-1}$ $t_{N-1}$
The first line provides the number of rooms $N$ ($1 \leq N \leq 100,000$). Each of the subsequent $N$ lines provides the point of the $i$-th room $p_i$ ($-100 \leq p_i \leq 100$) in integers. Each of the subsequent lines following these provides the information on the road directly connecting two rooms, where $s_i$ and $t_i$ ($1 \leq s_i < t_i \leq N$) represent the numbers of the two rooms connected by it. Not a single pair of rooms are connected by more than one road.
Output
Output the maximum possible score Bob can gain.
Sample Input 1
7
6
1
-1
4
3
3
1
1 2
2 3
3 4
3 5
5 6
5 7
Sample Output 1
10
For example, the score is maximized by routing the rooms in the following sequence: $6 \rightarrow 5 \rightarrow 3 \rightarrow 4 \rightarrow 3 \rightarrow 2 \rightarrow 1$.
Sample Input 2
4
5
0
1
1
1 2
2 3
2 4
Sample Output 2
5
The score is maximized if Tora-Tora stats his journey from room 1 and ends in the same room.

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define rep2(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rrep(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define rrep2(i, a, b) for (int i = (int)(b) - 1; i >= (int)(a); --i)

#define all(v) begin(v), end(v)
#define rall(v) rbegin(v), rend(v)

using namespace std;

using ll = long long;
using PLL = pair<ll, ll>;

template<class T, class U> bool chmin(T& a, const U& b) { return a > b ? a = b, true : false; }
template<class T, class U> bool chmax(T& a, const U& b) { return a < b ? a = b, true : false; }

constexpr ll inf = 1e18;
constexpr int MOD = 1000000007;

int main() {
    int N; scanf("%d", &N);
    vector<ll> P(N, -1);
    rep (i, N) scanf("%lld", &P[i]);
    vector<vector<int>> G(N);
    rep (_, N - 1) {
        int a, b; scanf("%d%d", &a, &b);
        --a; --b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    auto op = [&](PLL p, PLL q) -> PLL {
        ll a = 0, b = 0;
        chmax(a, max(p.first, q.first));
        chmax(b, max(p.second, q.second));
        chmax(a, p.first + q.first);
        chmax(b, p.first + q.second);
        chmax(b, p.second + q.first);
        return {a, b};
    };
    vector<PLL> memo1(N), memo2(N);
    auto dfs1 = [&](auto&& self, int v, int p) -> PLL {
        PLL res = {0, 0};
        for (auto u : G[v]) if (u != p) res = op(res, self(self, u, v));
        memo1[v] = {res.first + P[v] - 2, res.second + P[v] - 1};
        return memo1[v];
    };
    dfs1(dfs1, 0, -1);
    ll ans = -inf;
    auto dfs2 = [&](auto&& self, int v, int p) -> void {
        int M = G[v].size();
        vector<PLL> cumL(M + 1, PLL{0, 0}), cumR(M + 1, {0, 0});
        rep (i, M) {
            int u = G[v][i];
            PLL t = u == p ? memo2[v] : memo1[u];
            cumL[i + 1] = op(cumL[i], t);
        }
        rrep (i, M) {
            int u = G[v][i];
            PLL t = u == p ? memo2[v] : memo1[u];
            cumR[i] = op(cumR[i + 1], t);
        }
        auto res = cumL[M];
        chmax(ans, max(res.first, res.second) + P[v]);
        rep (i, M) {
            int u = G[v][i];
            if (u == p) continue;
            PLL t = op(cumL[i], cumR[i + 1]);
            memo2[u] = {t.first + P[v] - 2, t.second + P[v] - 1};
            self(self, u, v);
        }
    };
    dfs2(dfs2, 0, -1);
    printf("%lld\n", ans);
}
accuracy: 1
time_ms: 30
memory_kb: 37464
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ld=long double;
#define fi first
#define se second
#define i128 __int128_t
#define all(x) x.begin(),x.end()
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define si(a) (long)(a.size())
template<typename T>bool chmin(T&a,T b){return b<a?(a=b,1):0;}
template<typename T>bool chmax(T&a,T b){return b>a?(a=b,1):0;}
const int INF=1e9+100;
const long INFL=3e18+100;
struct _ {
   _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

int main(){

    int N;
    cin>>N;
    vector<int> P(N);
    rep(i,N)cin>>P[i];
    vector<vector<int>> G(N);
    rep(i,N-1){
        int s,t;
        cin>>s>>t;
        s--;t--;
        G[s].push_back(t);
        G[t].push_back(s);
    }
    long ans=-INFL;
    auto dfs=[&](auto dfs, int v, int p)->array<long,3> {
        array<long,3> dp={P[v],P[v],P[v]};
        
        for(int e: G[v]){
            if(e==p) continue;
            array<long,3> ret=dfs(dfs, e, v);

            chmax(dp[2], dp[2]+ret[0]-2);
            chmax(dp[2], dp[0]+ret[2]-2);
            chmax(dp[2], dp[1]+ret[1]-1);

            chmax(dp[1], dp[1]+ret[0]-2);
            chmax(dp[1], dp[0]+ret[1]-2+1);

            chmax(dp[0], dp[0]+ret[0]-2);
        }
        rep(i,3) chmax(ans, dp[i]);

        // cout<<v+1<<": ";
        // rep(i,3) cout<<dp[i]<<" ";
        // cout<<"\n";
        return dp;
    };
    dfs(dfs, 0, -1);

    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 20
memory_kb: 23116
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define pb push_back
#define rep(i,N) for(int i =0;i<(int)N;i++)
#define all(x) x.begin(),x.end()
int main(){
    int N;cin>>N;
    vector<ll>P(N);
    rep(i,N)cin>>P[i];
    vector<vector<int>>G(N);
    rep(i,N-1){
        int a,b;cin>>a>>b;
        a--,b--;
        G[a].pb(b);
        G[b].pb(a);
    }
    queue<int>Q;
    stack<int>order;
    Q.push(0);
    vector<int>seen(N,0);
    while(!Q.empty()){
        int v = Q.front();
        Q.pop();
        order.push(v);
        seen[v]=1;
        for(auto e : G[v]){
            if(seen[e]==0){
                Q.push(e);
            }
        }
    }
    ll ans = P[0];
    vector<ll>A(N,-998244353),B(N,-998244353),C(N,-998244353);
    while(!order.empty()){
        int v = order.top();order.pop();
        seen[v]=2;
        A[v]=max(P[v],A[v]);
        B[v]=max(P[v],B[v]);
        vector<ll>X,Y,W;
        ll sum = 0;
        for(auto e : G[v]){
            if(seen[e]==2){
                X.pb(A[e]);
                Y.pb(B[e]);
                W.pb(C[e]);
            }
        }
        for(auto e : X){
            if(e>=2)sum+=e-2;
        }
        vector<ll>Z;
        rep(i,X.size()){
            if(X[i]<2)Z.pb(Y[i]-1);
            else Z.pb(Y[i]-X[i]+1);
        }
        sort(all(Z));
        reverse(all(Z));
        if(X.size()>=2){
            C[v]=max(C[v],P[v]+sum+Z[0]+Z[1]);
        }
        A[v]=max(A[v],P[v]+sum);
        rep(i,X.size()){
            if(X[i]>=2){
                B[v]=max(B[v],P[v]+sum-X[i]+1+Y[i]);
                C[v]=max(C[v],P[v]+sum-X[i]+W[i]);
            }
            else {
                B[v]=max(B[v],P[v]+sum+Y[i]-1);
                C[v]=max(C[v],P[v]+sum+W[i]-2);
            }
        }
        ans = max({ans,A[v],B[v],C[v]});
    }
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 50
memory_kb: 16768
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ld=long double;
#define fi first
#define se second
#define i128 __int128_t
#define all(x) x.begin(),x.end()
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define si(a) (long)(a.size())
template<typename T>bool chmin(T&a,T b){return b<a?(a=b,1):0;}
template<typename T>bool chmax(T&a,T b){return b>a?(a=b,1):0;}
const int INF=1e9+100;
const long INFL=3e18+100;
struct _ {
   _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

int main(){

    int N;
    cin>>N;
    vector<int> P(N);
    rep(i,N)cin>>P[i];
    vector<vector<int>> G(N);
    rep(i,N-1){
        int s,t;
        cin>>s>>t;
        s--;t--;
        G[s].push_back(t);
        G[t].push_back(s);
    }
    long ans=-INFL;
    auto dfs=[&](auto dfs, int v, int p)->array<long,3> {
        array<long,3> dp={P[v],P[v],P[v]};
        
        for(int e: G[v]){
            if(e==p) continue;
            array<long,3> ret=dfs(dfs, e, v);

            chmax(dp[2], dp[2]+ret[0]-2);
            chmax(dp[2], dp[0]+ret[2]-2);
            chmax(dp[2], dp[1]+ret[1]-1);

            chmax(dp[1], dp[1]+ret[0]-2);
            chmax(dp[1], dp[0]+ret[1]-2+1);

            chmax(dp[0], dp[0]+ret[0]-2);
        }
        rep(i,3) chmax(ans, dp[i]);

        // cout<<v+1<<": ";
        // rep(i,3) cout<<dp[i]<<" ";
        // cout<<"\n";
        return dp;
    };
    dfs(dfs, 0, -1);

    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 10
memory_kb: 18836
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;

struct node {
    int a, b, c;
};
int ans = -1e9;
const int maxn = 1e5 + 5;
node dp[maxn];
int a[maxn];
vector<int> g[maxn];

void dfs(int u , int p) {
    int mx1 = 0, mx2 = 0, ss = 0;
    int summ = a[u];
    for (int v : g[u]) {
        if(v == p) continue;
        dfs(v, u);
        node q = dp[v];
        int nn = 0;
        if (q.a >= 2) {
            nn = q.a - 2;
            summ += nn;
        }
        int x = q.b - 1 - nn;
        if (mx1 < x) {
            mx2 = mx1;
            mx1 = x;
        } else {
            if (mx2 < x)
            mx2 = x;
        }
        ss = max(ss, q.c - 2 - nn);
    }
    dp[u] = {summ, summ + mx1, summ + max(ss , mx1 + mx2)};
    ans = max(ans, dp[u].c);
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    for (int i = 0 ; i < n ; i++) {
        cin >> a[i];
    }
    for (int i = 1 ; i < n ; i++) {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].emplace_back(v);
        g[v].emplace_back(u);
    }
    dfs(0, -1);
    cout << ans << '\n';
}
accuracy: 1
time_ms: 20
memory_kb: 19748
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;

struct node {
    int a, b, c;
};
int ans = -1e9;
const int maxn = 1e5 + 5;
node dp[maxn];
int a[maxn];
vector<int> g[maxn];

void dfs(int u , int p) {
    int mx1 = 0, mx2 = 0, ss = 0;
    int summ = a[u];
    for (int v : g[u]) {
        if(v == p) continue;
        dfs(v, u);
        node q = dp[v];
        int nn = 0;
        if (q.a >= 2) {
            nn = q.a - 2;
            summ += nn;
        }
        int x = q.b - 1 - nn;
        if (mx1 < x) {
            mx2 = mx1;
            mx1 = x;
        } else {
            if (mx2 < x)
            mx2 = x;
        }
        ss = max(ss, q.c - 2 - nn);
    }
    dp[u] = {summ, summ + mx1, summ + max(ss , mx1 + mx2)};
    ans = max(ans, summ + mx1 + mx2);
    ans = max(ans, summ + ss);
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    for (int i = 0 ; i < n ; i++) {
        cin >> a[i];
    }
    for (int i = 1 ; i < n ; i++) {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        g[u].emplace_back(v);
        g[v].emplace_back(u);
    }
    dfs(0, -1);
    cout << ans << '\n';
}
accuracy: 1
time_ms: 20
memory_kb: 19776
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;

int ans = -1e9 , n;
vector<int> a;
vector<vector<int>> g;

struct node {
    int a, b, c;
};

node dfs(int u , int p) {
	int mx1 = 0, mx2 = 0, ss = 0;
	int summ = a[u];
	for (int v : g[u]) {
        if(v == p) continue;
		node q = dfs(v, u);
		int nn = 0;
		if (q.a >= 2) {
		    nn = q.a - 2;
            summ += nn;
		}
		int x = q.b - 1 - nn;
		if (mx1 < x) {
			mx2 = mx1;
			mx1 = x;
		} else {
            if (mx2 < x)
                mx2 = x;
		}
		ss = max(ss, q.c - 2 - nn);
	}
	ans = max(ans, summ + mx1 + mx2);
	ans = max(ans, summ + ss);
	return {summ, summ + mx1, summ + max(ss , mx1 + mx2)};
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n;
    g.resize(n);
    a.resize(n);
    for (int i = 0 ; i < n ; i++) {
        cin >> a[i];
    }
	for (int i = 1 ; i < n ; i++) {
		int u, v;
		cin >> u >> v;
		u--;
		v--;
		g[u].emplace_back(v);
		g[v].emplace_back(u);
	}
	dfs(0, -1);
	cout << ans << '\n';
}
accuracy: 1
time_ms: 20
memory_kb: 19980
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0, c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(ll n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}
 
int N;
vector<int> roomPoints;
vector<vector<int>> graph;
 
vector<ll> dp, upVal;
vector<int> par;
 
void dfs_dp(int u, int parent) {
    par[u] = parent;
    ll sum = 0;
    for (int v : graph[u]) {
        if (v == parent) continue;
        dfs_dp(v, u);
        sum += max(0LL, dp[v]);
    }
    dp[u] = roomPoints[u] - 2 + sum;
}
 
void dfs_up(int u, int parent) {
    ll sumContrib = max(0LL, upVal[u]);
    for (int v : graph[u]) {
        if (v == parent) continue;
        sumContrib += max(0LL, dp[v]);
    }
    for (int v : graph[u]) {
        if (v == parent) continue;
        upVal[v] = roomPoints[u] - 2 + (sumContrib - max(0LL, dp[v]));
        dfs_up(v, u);
    }
}
 
vector<ll> Fval;
 
void compute_F() {
    Fval.resize(N+1, 0);
    for (int u = 1; u <= N; u++){
        ll sum = 0;
        for (int v : graph[u]){
            if(v == par[u]) sum += max(0LL, upVal[u]);
            else            sum += max(0LL, dp[v]);
        }
        Fval[u] = roomPoints[u] + sum;
    }
}
 
ll getCost(int u, int v) {
    if (par[v] == u)
        return max(0LL, dp[v]) + max(0LL, upVal[v]) + 1;
    else if (par[u] == v)
        return max(0LL, dp[u]) + max(0LL, upVal[u]) + 1;
    return 0;
}
 
ll ansFinal = -LLONG_MAX;
 
ll dfs_diameter(int u, int parent) {
    ll best1 = 0, best2 = 0;
    for (int v : graph[u]) {
        if (v == parent) continue;
        ll subChain = dfs_diameter(v, u);
        ll cand = subChain - getCost(u, v);
        if(cand < 0) cand = 0;
        if(cand > best1) {
            best2 = best1;
            best1 = cand;
        } else if(cand > best2) best2 = cand;
    }
    ll chain = Fval[u] + best1;
    ansFinal = max(ansFinal, Fval[u] + best1 + best2);
    return chain;
}
 
int main() {
    N = Cin();
    roomPoints.resize(N+1);
    for (int i = 1; i <= N; i++) roomPoints[i] = Cin();

    graph.resize(N+1);
    par.resize(N+1, 0);
    dp.resize(N+1, 0);
    upVal.resize(N+1, 0);
    
    for (int i = 1; i < N; i++){
        int s = Cin(), t = Cin();
        graph[s].push_back(t);
        graph[t].push_back(s);
    }
    
    if(N == 1){
        Cout(roomPoints[1]);
        return 0;
    }
    
    dfs_dp(1, 0);
    upVal[1] = 0;
    dfs_up(1, 0);
    compute_F();
    
    ansFinal = -LLONG_MAX;
    dfs_diameter(1, 0);
    Cout(ansFinal);
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 19420
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <functional>
using namespace std;

int main()
{
    int N;
    cin>>N;
    vector<int> p(N);
    for (int &t: p)
        cin>>t;
    vector<vector<int>> E(N);
    for (int i=0; i<N-1; i++)
    {
        int s, t;
        cin>>s>>t;
        E[s-1].push_back(t-1);
        E[t-1].push_back(s-1);
    }

    // T1[c]: 頂点cを通り、スタートもゴールもcを頂点とする部分木に無い場合に、cを頂点とする部分木で得られる最高得点。
    vector<int> T1(N);
    // T2[c]: 頂点cを通り、スタートかゴールのどちらか一方がcを頂点とする部分木にある場合に、cを頂点とする部分木で得られる最高得点。
    vector<int> T2(N);
    // T3[c]: 頂点cを通り、スタートもゴールもcを頂点とする部分木にある場合に、cを頂点とする部分木で得られる最高得点。
    vector<int> T3(N);

    function<void(int, int)> f = [&](int c, int parent)
        {
            T1[c] = p[c];
            T2[c] = p[c];
            T3[c] = p[c];

            for (int e: E[c])
                if (e!=parent)
                {
                    f(e, c);

                    // 部分木eを考慮する前の値を退避しておく。
                    int t1 = T1[c];
                    int t2 = T2[c];
                    int t3 = T3[c];

                    // T1: 次のうちの最高得点。
                    // - 部分木eに行かない。
                    // - 部分木eに行って戻ってくる。
                    T1[c] = max({
                        t1,
                        t1+T1[e]-2,
                    });

                    // T2: 次のうちの最高得点。
                    // - 部分木eに行かない。
                    // - 部分木eより前に片道があり、部分木eは行って戻ってくる。
                    // - 部分木eより前は行って戻ってきて、部分木eは片道。
                    T2[c] = max({
                        t2,
                        t2+T1[e]-2,
                        t1+T2[e]-1,
                    });

                    // T3: 次のうちの最高得点。
                    // - 部分木eに行かない。
                    // - 部分木eより前にスタートもゴールもあり、部分木eは行って戻ってくる。
                    // - 部分木eより前は行って戻ってきて、部分木eにスタートもゴールもある。
                    // - 部分木eより前も、部分木eも片道。
                    T3[c] = max({
                        t3,
                        t3+T1[e]-2,
                        t1+T3[e]-2,
                        t2+T2[e]-1,
                    });
                }
        };
    f(0, -1);

    // ここまでの各部分木で得られる最高得点の中に、木全体での最高得点がある。
    int ans = -999999999;
    for (int t: T1)
        ans = max(ans, t);
    for (int t: T2)
        ans = max(ans, t);
    for (int t: T3)
        ans = max(ans, t);
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 50
memory_kb: 22604
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <functional>
using namespace std;

int main()
{
    int N;
    cin>>N;
    vector<int> p(N);
    for (int &t: p)
        cin>>t;
    vector<vector<int>> E(N);
    for (int i=0; i<N-1; i++)
    {
        int s, t;
        cin>>s>>t;
        E[s-1].push_back(t-1);
        E[t-1].push_back(s-1);
    }

    // T1[c]: 頂点cを通り、スタートもゴールもcを頂点とする部分木に無い場合に、cを頂点とする部分木で得られる最高得点。
    vector<int> T1(N);
    // T2[c]: 頂点cを通り、スタートかゴールのどちらか一方がcを頂点とする部分木にある場合に、cを頂点とする部分木で得られる最高得点。
    vector<int> T2(N);
    // T3[c]: 頂点cを通り、スタートもゴールもcを頂点とする部分木にある場合に、cを頂点とする部分木で得られる最高得点。
    vector<int> T3(N);

    function<void(int, int)> f = [&](int c, int parent)
        {
            T1[c] = p[c];
            T2[c] = p[c];
            T3[c] = p[c];

            for (int e: E[c])
                if (e!=parent)
                {
                    f(e, c);

                    // 部分木eを考慮する前の値を退避しておく。
                    int t1 = T1[c];
                    int t2 = T2[c];
                    int t3 = T3[c];

                    // T1: 次のうちの最高得点。
                    // - 部分木eに行かない。
                    // - 部分木eに行って戻ってくる。
                    T1[c] = max({
                        t1,
                        t1+T1[e]-2,
                    });

                    // T2: 次のうちの最高得点。
                    // - 部分木eに行かない。
                    // - 部分木eより前に片道があり、部分木eは行って戻ってくる。
                    // - 部分木eより前は行って戻ってきて、部分木eは片道。
                    T2[c] = max({
                        t2,
                        t2+T1[e]-2,
                        t1+T2[e]-1,
                    });

                    // T3: 次のうちの最高得点。
                    // - 部分木eに行かない。
                    // - 部分木eより前にスタートもゴールもあり、部分木eは行って戻ってくる。
                    // - 部分木eより前は行って戻ってきて、部分木eにスタートもゴールもある。
                    // - 部分木eより前も、部分木eも片道。
                    T3[c] = max({
                        t3,
                        t3+T1[e]-2,
                        t1+T3[e]-2,
                        t2+T2[e]-1,
                    });
                }
        };
    f(0, -1);

    int ans = -999999999;
    for (int t: T1)
        ans = max(ans, t);
    for (int t: T2)
        ans = max(ans, t);
    for (int t: T3)
        ans = max(ans, t);
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 50
memory_kb: 22548
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define int long long

/*
17:29~17:43
6:25~7:05
13:10~13:19
17:15~
*/

template <class E, class V, E (*merge)(E, E), E (*e)(), E (*put_edge)(V, int), V (*put_vertex)(E, int)>
struct RerootingDP {
    struct edge {
        int to, idx, xdi;
    };
    RerootingDP(int n_ = 0) : n(n_), inner_edge_id(0) {
        es.resize(2*n-2);
        start.resize(2*n-2);
        if (n == 1) es_build();
    }
    void add_edge(int u, int v, int idx, int xdi){
        start[inner_edge_id] = u;
        es[inner_edge_id] = {v,idx,xdi};
        inner_edge_id++;
        start[inner_edge_id] = v;
        es[inner_edge_id] = {u,xdi,idx};
        inner_edge_id++;
        if (inner_edge_id == 2*n-2){
            es_build();
        }
    }
    vector<V> build(int root_ = 0){
        root = root_;
        vector<V> subdp(n); subdp[0] = put_vertex(e(),0);
        outs.resize(n);
        vector<int> geta(n+1,0);
        for (int i = 0; i < n; i++) geta[i+1] = start[i+1] - start[i] - 1;
        geta[root+1]++;
        for (int i = 0; i < n; i++) geta[i+1] += geta[i];
        auto dfs = [&](auto sfs, int v, int f) -> void {
            E val = e();
            for (int i = start[v]; i < start[v+1]; i++){
                if (es[i].to == f){
                    swap(es[start[v+1]-1],es[i]);
                }
                if (es[i].to == f) continue;
                sfs(sfs,es[i].to,v);
                E nval = put_edge(subdp[es[i].to],es[i].idx);
                outs[geta[v]++] = nval;
                val = merge(val,nval);
            }
            subdp[v] = put_vertex(val, v);
        };
        dfs(dfs,root,-1);
        return subdp;
    }
    vector<V> reroot(){
        vector<E> reverse_edge(n);
        reverse_edge[root] = e();
        vector<V> answers(n);
        auto dfs = [&](auto sfs, int v) -> void {
            int le = outs_start(v);
            int ri = outs_start(v+1);
            int siz = ri - le;
            vector<E> rui(siz+1);
            rui[siz] = e();
            for (int i = siz-1; i >= 0; i--){
                rui[i] = merge(outs[le+i],rui[i+1]);
            }
            answers[v] = put_vertex(merge(rui[0],reverse_edge[v]),v);
            E lui = e();
            for (int i = 0; i < siz; i++){
                V rdp = put_vertex(merge(merge(lui,rui[i+1]),reverse_edge[v]),v);
                reverse_edge[es[start[v]+i].to] = put_edge(rdp,es[start[v]+i].xdi);
                lui = merge(lui,outs[le+i]);
                sfs(sfs,es[start[v]+i].to);
            }
        };
        dfs(dfs,root);
        return answers;
    }
    private:
    int n, root, inner_edge_id;
    vector<E> outs;
    vector<edge> es;
    vector<int> start;
    int outs_start(int v){
        int res = start[v] - v;
        if (root < v) res++;
        return res;
    }
    void es_build(){
        vector<edge> nes(2*n-2);
        vector<int> nstart(n+2,0);
        for (int i = 0; i < 2*n-2; i++) nstart[start[i]+2]++;
        for (int i = 0; i < n; i++) nstart[i+1] += nstart[i];
        for (int i = 0; i < 2*n-2; i++) nes[nstart[start[i]+1]++] = es[i];
        swap(es,nes);
        swap(start,nstart);
    }
};

int P[100009];

using S=array<int,2>;

S merge(S x,S y){
	S z;
	z[0]=max<int>(0,x[0])+max<int>(0,y[0]);
	z[1]=max(max<int>(0,x[0])+max<int>(0,y[1]),max<int>(0,x[1])+max<int>(0,y[0]));
	return z;
}

S e(){
	return {0,0};
}

S put_edge(S x,int idx){
	return {x[0]-2,x[1]-1};
}

S put_vertex(S x,int idx){
	return {max<int>(0,x[0])+P[idx],max<int>(0,x[1])+P[idx]};
}

signed main(){
	int n;cin>>n;
	for(int i=0;i<n;i++){
		cin>>P[i];
	}

	RerootingDP<S,S,merge,e,put_edge,put_vertex> g(n);

	for(int i=0;i<n-1;i++){
		int s,t;cin>>s>>t;
		s--;t--;
		g.add_edge(s,t,i,i);
	}

	g.build();

	auto res=g.reroot();

	int ans=-1e18;
	for(int i=0;i<n;i++){
		ans=max(ans,res[i][0]);
		ans=max(ans,res[i][1]);
	}

	cout<<ans<<endl;
}
accuracy: 1
time_ms: 60
memory_kb: 34152
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for(int i = 0;i < n;i++){
		cin >> a[i];
	}
	vector<vector<int>> g(n,vector<int>());
	for(int i = 0;i < n - 1;i++){
		int u,v;
		cin >> u >> v;
		u--;v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector<int> dist(n,-1);
	{
		queue<int> q;
		dist[0] = 0;
		q.push(0);
		while(!q.empty()){
			int it = q.front();
			q.pop();
			for(int i : g[it]){
				if(dist[i] != -1) continue;
				dist[i] = dist[it] + 1;
				q.push(i);
			}
		}
	}
	int ans = -INT_MAX;
	vector<int> e(n,-INT_MAX);
	auto f = [&](auto f,int x) -> pair<int,int> {
		pair<int,int> res = {a[x],a[x]};
		vector<pair<pair<int,int>,int>> t;
		int p = -1;
		int tmp = 0;
		for(int i : g[x]){
			p++;
			if(dist[i] < dist[x]){
				t.push_back({{-1000,0},p});
				continue;
			}
			pair<int,int> r = f(f,i);
			if(e[x] < e[i] - 2 + a[x]){
				e[x] = e[i] - 2 + a[x];
				tmp = max(r.second - 2,0);
			}
			t.push_back({r,p});
			if(r.second - 2 >= 0){
				res.second += r.second - 2;
			}
		}
		auto com = [](pair<pair<int,int>,int> a,pair<pair<int,int>,int> b) -> bool {
			if(a.first.first == -1000 && b.first.first == -1000) return true;
			if(a.first.first == -1000) return false;
			if(b.first.first == -1000) return true;
			a.first = {max(0,a.first.first - 1),max(0,a.first.second - 2)};
			b.first = {max(0,b.first.first - 1),max(0,b.first.second - 2)};
			return a.first.first - a.first.second > b.first.first - b.first.second;
		};
		sort(t.begin(),t.end(),com);
		int cnt = -1;
		int now = a[x];
		for(int i : g[x]){
			cnt++;
			if(cnt == 0){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.first - 1,0);
			}else if(cnt == 1){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.second - 2,0);
			}else{
				now += max(t[cnt].first.second - 2,0);
				res.first += max(t[cnt].first.second - 2,0);
			}
			e[x] += max(t[cnt].first.second - 2,0);
		}
		e[x] -= tmp;
		e[x] = max({e[x],now,res.first,res.second});
		ans = max(ans,e[x]);
		return res;
	};
	f(f,0);
	cout << ans << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 33180
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for(int i = 0;i < n;i++){
		cin >> a[i];
	}
	vector<vector<int>> g(n,vector<int>());
	for(int i = 0;i < n - 1;i++){
		int u,v;
		cin >> u >> v;
		u--;v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector<int> dist(n,-1);
	{
		queue<int> q;
		dist[0] = 0;
		q.push(0);
		while(!q.empty()){
			int it = q.front();
			q.pop();
			for(int i : g[it]){
				if(dist[i] != -1) continue;
				dist[i] = dist[it] + 1;
				q.push(i);
			}
		}
	}
	int ans = -INT_MAX;
	vector<int> e(n,-INT_MAX);
	auto f = [&](auto f,int x) -> pair<int,int> {
		pair<int,int> res = {a[x],a[x]};
		vector<pair<pair<int,int>,int>> t;
		int p = -1;
		for(int i : g[x]){
			p++;
			if(dist[i] < dist[x]){
				t.push_back({{-1000,0},p});
				continue;
			}
			pair<int,int> r = f(f,i);
			e[x] = max(e[x],e[i] - 2 + a[x]);
			t.push_back({r,p});
			if(r.second - 2 >= 0){
				res.second += r.second - 2;
			}
		}
		auto com = [](pair<pair<int,int>,int> a,pair<pair<int,int>,int> b) -> bool {
			a.first = {max(0,a.first.first - 1),max(0,a.first.second - 2)};
			b.first = {max(0,b.first.first - 1),max(0,b.first.second - 2)};
			return a.first.first - a.first.second > b.first.first - b.first.second;
		};
		sort(t.begin(),t.end(),com);
		int cnt = -1;
		int now = a[x];
		for(int i : g[x]){
			cnt++;
			if(cnt == 0){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.first - 1,0);
			}else if(cnt == 1){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.second - 2,0);
			}else{
				now += max(t[cnt].first.second - 2,0);
				res.first += max(t[cnt].first.second - 2,0);
			}
		}
		e[x] = max({e[x],now,res.first,res.second});
		ans = max(ans,e[x]);
		return res;
	};
	f(f,0);
	cout << ans << endl;
}
accuracy: 0.625
time_ms: 50
memory_kb: 33184
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for(int i = 0;i < n;i++){
		cin >> a[i];
	}
	vector<vector<int>> g(n,vector<int>());
	for(int i = 0;i < n - 1;i++){
		int u,v;
		cin >> u >> v;
		u--;v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector<int> dist(n,-1);
	{
		queue<int> q;
		dist[0] = 0;
		q.push(0);
		while(!q.empty()){
			int it = q.front();
			q.pop();
			for(int i : g[it]){
				if(dist[i] != -1) continue;
				dist[i] = dist[it] + 1;
				q.push(i);
			}
		}
	}
	int ans = -INT_MAX;
	vector<int> e(n,-INT_MAX);
	auto f = [&](auto f,int x) -> pair<int,int> {
		pair<int,int> res = {a[x],a[x]};
		vector<pair<pair<int,int>,int>> t;
		int p = -1;
		for(int i : g[x]){
			p++;
			if(dist[i] < dist[x]){
				t.push_back({{-1000,0},p});
				continue;
			}
			pair<int,int> r = f(f,i);
			e[x] = max(e[x],e[i] - 2 + a[x]);
			t.push_back({r,p});
			if(r.second - 2 >= 0){
				res.second += r.second - 2;
			}
		}
		auto com = [](pair<pair<int,int>,int> a,pair<pair<int,int>,int> b) -> bool {
			if((a.first.first < 0 || a.first.second < 0) && (b.first.first < 0 || b.first.second < 0)){
				return a.first.first < b.first.first;
			}
			if(a.first.first < 0 || a.first.second < 0) return false;
			if(b.first.first < 0 || b.first.second < 0) return true;
			if(a.first.first < 1 || a.first.second < 1) return false;
			if(b.first.first < 1 || b.first.second < 1) return true;
			if(a.first.second - a.first.first == b.first.second - b.first.first){
				return a.first.first > b.first.first;
			}
			return a.first.second - a.first.first < b.first.second - b.first.first;
		};
		sort(t.begin(),t.end(),com);
		int cnt = -1;
		int now = a[x];
		for(int i : g[x]){
			cnt++;
			if(cnt == 0){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.first - 1,0);
			}else if(cnt == 1){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.second - 2,0);
			}else{
				now += max(t[cnt].first.second - 2,0);
				res.first += max(t[cnt].first.second - 2,0);
			}
		}
		e[x] = max({e[x],now,res.first,res.second});
		ans = max(ans,e[x]);
		return res;
	};
	f(f,0);
	cout << ans << endl;
}
accuracy: 0.28125
time_ms: 50
memory_kb: 33028
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for(int i = 0;i < n;i++){
		cin >> a[i];
	}
	vector<vector<int>> g(n,vector<int>());
	for(int i = 0;i < n - 1;i++){
		int u,v;
		cin >> u >> v;
		u--;v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector<int> dist(n,-1);
	{
		queue<int> q;
		dist[0] = 0;
		q.push(0);
		while(!q.empty()){
			int it = q.front();
			q.pop();
			for(int i : g[it]){
				if(dist[i] != -1) continue;
				dist[i] = dist[it] + 1;
				q.push(i);
			}
		}
	}
	int ans = -INT_MAX;
	vector<int> e(n,-INT_MAX);
	auto f = [&](auto f,int x) -> pair<int,int> {
		pair<int,int> res = {a[x],a[x]};
		vector<pair<pair<int,int>,int>> t;
		int p = -1;
		for(int i : g[x]){
			p++;
			if(dist[i] < dist[x]){
				t.push_back({{-1000,0},p});
				continue;
			}
			pair<int,int> r = f(f,i);
			e[x] = max(e[x],e[i] - 2 + a[x]);
			t.push_back({r,p});
			if(r.second - 2 >= 0){
				res.second += r.second - 2;
			}
		}
		auto com = [](pair<pair<int,int>,int> a,pair<pair<int,int>,int> b) -> bool {
			if((a.first.first < 0 || a.first.second < 0) && (b.first.first < 0 || b.first.second < 0)){
				return a.first.first < b.first.first;
			}
			if(a.first.first < 0 || a.first.second < 0) return false;
			if(b.first.first < 0 || b.first.second < 0) return true;
			if(a.first.second - a.first.first == b.first.second - b.first.first){
				return a.first.first > b.first.first;
			}
			return a.first.second - a.first.first < b.first.second - b.first.first;
		};
		sort(t.begin(),t.end(),com);
		int cnt = -1;
		int now = a[x];
		for(int i : g[x]){
			cnt++;
			if(cnt == 0){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.first - 1,0);
			}else if(cnt == 1){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.second - 2,0);
			}else{
				now += max(t[cnt].first.second - 2,0);
				res.first += max(t[cnt].first.second - 2,0);
			}
		}
		e[x] = max({e[x],now,res.first,res.second});
		ans = max(ans,e[x]);
		return res;
	};
	f(f,0);
	cout << ans << endl;
}
accuracy: 0.28125
time_ms: 50
memory_kb: 33108
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for(int i = 0;i < n;i++){
		cin >> a[i];
	}
	vector<vector<int>> g(n,vector<int>());
	for(int i = 0;i < n - 1;i++){
		int u,v;
		cin >> u >> v;
		u--;v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	vector<int> dist(n,-1);
	{
		queue<int> q;
		dist[0] = 0;
		q.push(0);
		while(!q.empty()){
			int it = q.front();
			q.pop();
			for(int i : g[it]){
				if(dist[i] != -1) continue;
				dist[i] = dist[it] + 1;
				q.push(i);
			}
		}
	}
	int ans = -INT_MAX;
	vector<int> e(n,-INT_MAX);
	auto f = [&](auto f,int x) -> pair<int,int> {
		pair<int,int> res = {a[x],a[x]};
		vector<pair<pair<int,int>,int>> t;
		int p = -1;
		for(int i : g[x]){
			p++;
			if(dist[i] < dist[x]){
				t.push_back({{-1000,0},p});
				continue;
			}
			pair<int,int> r = f(f,i);
			e[x] = max(e[x],e[i] - 2 + a[x]);
			t.push_back({r,p});
			if(r.second - 2 >= 0){
				res.second += r.second - 2;
			}
		}
		auto com = [](pair<pair<int,int>,int> a,pair<pair<int,int>,int> b) -> bool {
			if(a.first.first < 0 && b.first.first < 0){
				return a.first.first < b.first.first;
			}
			if(a.first.first < 0) return false;
			if(b.first.first < 0) return true;
			if(a.first.second - a.first.first == b.first.second - b.first.first){
				return a.first.first > b.first.first;
			}
			return a.first.second - a.first.first < b.first.second - b.first.first;
		};
		sort(t.begin(),t.end(),com);
		int cnt = -1;
		int now = a[x];
		for(int i : g[x]){
			cnt++;
			if(cnt == 0){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.first - 1,0);
			}else if(cnt == 1){
				now += max(t[cnt].first.first - 1,0);
				res.first += max(t[cnt].first.second - 2,0);
			}else{
				now += max(t[cnt].first.second - 2,0);
				res.first += max(t[cnt].first.second - 2,0);
			}
		}
		e[x] = max({e[x],now,res.first,res.second});
		ans = max(ans,e[x]);
		return res;
	};
	f(f,0);
	cout << ans << endl;
}
accuracy: 0.625
time_ms: 50
memory_kb: 33152
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

using S = array<int, 3>;

int main() {
  int N;
  cin >> N;
  vector<int> p(N);
  for(int i = 0; i < N; i++) {
    cin >> p[i];
  }
  vector<vector<int>> G(N);
  for(int i = 0; i < N-1; i++) {
    int s, t;
    cin >> s >> t;
    s--, t--;
    G[s].push_back(t);
    G[t].push_back(s);
  }
  const int INF = 1e8;
  vector<S> dp(N);
  auto dfs = [&](auto dfs, int cur, int par) -> void {
    for(int &nxt : G[cur]) {
      if(par == nxt) continue;
      dfs(dfs, nxt, cur);
    }
    dp[cur] = S{p[cur], p[cur], p[cur]};
    { // 頂点 cur でマージ
      int merged = 0;
      vector<int> diff = {0, 0};
      for(int &nxt : G[cur]) {
        if(par == nxt) continue;
        int x = max(0, dp[nxt][1]-1);
        int y = max(0, dp[nxt][2]-2);
        merged += y;
        diff.push_back(x-y);
      }
      sort(diff.rbegin(), diff.rend());
      merged += diff[0]+diff[1];
      dp[cur][0] = max(dp[cur][0], merged+p[cur]);
    }
    { // 頂点 cur に値を伝播させる
      int merged = 0;
      for(int &nxt : G[cur]) {
        if(par == nxt) continue;
        int x = max(0, dp[nxt][1]-1);
        int y = max(0, dp[nxt][2]-2);
        merged += y;
      }
      dp[cur][2] = max(dp[cur][2], merged+p[cur]);
      for(int &nxt : G[cur]) {
        if(par == nxt) continue;
        int x = max(0, dp[nxt][1]-1);
        int y = max(0, dp[nxt][2]-2);
        int z = max(0, dp[nxt][0]-2);
        dp[cur][1] = max(dp[cur][1], merged-y+x+p[cur]);
        dp[cur][0] = max(dp[cur][0], merged-y+z+p[cur]);
      }
    }
    // cout << cur+1 << " : " << dp[cur][0] << " " << dp[cur][1] << " " << dp[cur][2] << endl;
  };
  dfs(dfs, 0, -1);
  int ans = -INF;
  for(int i = 0; i < N; i++) {
    ans = max({ans, dp[i][0], dp[i][1], dp[i][2]});
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 27260
final_rank: 12

code_snippet: #include <bits/stdc++.h>

int main() {
    int n;
    std::cin >> n;
    std::vector<int> ps(n);
    for (int i = 0; i < n; i++) std::cin >> ps[i];
    std::vector graph(n, std::vector<int>());
    for (int i = 0; i + 1 < n; i++) {
        int u, v;
        std::cin >> u >> v;
        u--; v--;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    std::vector dp(2, std::vector<int>(n));
    const int root = 0;
    {
        auto dfs = [&](auto self, int u, int p) -> void {
            dp[0][u] = ps[u];
            for (int v: graph[u]) {
                if (v == p) continue;
                self(self, v, u);
                dp[0][u] += std::max(dp[0][v] - 2, 0);
            }
            dp[1][u] = dp[0][u];
            for (int v: graph[u]) {
                if (v == p) continue;
                dp[1][u] = std::max(dp[1][u], dp[0][u] - std::max(dp[0][v] - 2, 0) + dp[1][v] - 1);
            }
        };
        dfs(dfs, root, -1);
    }
    int ans = -200;
    {
        auto dfs = [&](auto self, int u, int p, std::pair<int, int> pv) -> void {
            std::pair<int, int> now;
            now.first = ps[u];
            for (int v: graph[u]) {
                if (v == p) {
                    now.first += std::max(pv.first - 2, 0);
                } else{
                    now.first += std::max(dp[0][v] - 2, 0);
                }
            }
            now.second = now.first;
            for (int v: graph[u]) {
                if (v == p) {
                    now.second = std::max(now.second, now.first - std::max(pv.first - 2, 0) + pv.second - 1);
                } else {
                    now.second = std::max(now.second, now.first - std::max(dp[0][v] - 2, 0) + dp[1][v] - 1);
                }
            }
            ans = std::max(ans, now.second);
            int m = graph[u].size();
            std::vector<int> prefix(m + 1), suffix(m + 1);
            for (int i = 0; i < m; i++) {
                int v = graph[u][i];
                if (v == p) {
                    prefix[i + 1] = std::max(prefix[i], pv.second - std::max(pv.first - 2, 0) - 1);
                } else {
                    prefix[i + 1] = std::max(prefix[i], dp[1][v] - std::max(dp[0][v] - 2, 0) - 1);
                }
            }
            for (int i = m - 1; i >= 0; i--) {
                int v = graph[u][i];
                int j = m - i - 1;
                if (v == p) {
                    suffix[j + 1] = std::max(suffix[j], pv.second - std::max(pv.first - 2, 0) - 1);
                } else {
                    suffix[j + 1] = std::max(suffix[j], dp[1][v] - std::max(dp[0][v] - 2, 0) - 1);
                }
            }
            std::reverse(suffix.begin(), suffix.end());
            for (int i = 0; i < m; i++) {
                int v = graph[u][i];
                if (v == p) continue;
                std::pair<int, int> cv;
                cv.first = now.first - std::max(dp[0][v] - 2, 0);
                cv.second = cv.first + std::max(prefix[i], suffix[i + 1]);
                self(self, v, u, cv);
            }
        };
        dfs(dfs, root, -1, {0, 0});
    }
    std::cout << ans << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 32980
final_rank: 14

code_snippet: #include <bits/stdc++.h>

int main() {
    int n;
    std::cin >> n;
    std::vector<int> ps(n);
    for (int i = 0; i < n; i++) std::cin >> ps[i];
    std::vector graph(n, std::vector<int>());
    for (int i = 0; i + 1 < n; i++) {
        int u, v;
        std::cin >> u >> v;
        u--; v--;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    std::vector dp(2, std::vector<int>(n));
    const int root = 0;
    {
        auto dfs = [&](auto self, int u, int p) -> void {
            dp[0][u] = ps[u];
            for (int v: graph[u]) {
                if (v == p) continue;
                self(self, v, u);
                dp[0][u] += std::max(dp[0][v] - 2, 0);
            }
            dp[1][u] = dp[0][u];
            for (int v: graph[u]) {
                if (v == p) continue;
                dp[1][u] = std::max(dp[1][u], dp[0][u] - std::max(dp[0][v] - 2, 0) + dp[1][v] - 1);
            }
        };
        dfs(dfs, root, -1);
    }
    int ans = -200;
    {
        auto dfs = [&](auto self, int u, int p, std::pair<int, int> pv) -> void {
            std::pair<int, int> now;
            now.first = ps[u];
            for (int v: graph[u]) {
                if (v == p) {
                    now.first += std::max(pv.first - 2, 0);
                } else{
                    now.first += std::max(dp[0][v] - 2, 0);
                }
            }
            now.second = now.first;
            for (int v: graph[u]) {
                if (v == p) {
                    now.second = std::max(now.second, now.first - std::max(pv.first - 2, 0) + pv.second - 1);
                } else {
                    now.second = std::max(now.second, now.first - std::max(dp[0][v] - 2, 0) + dp[1][v] - 1);
                }
            }
            ans = std::max(ans, now.second);
            int m = graph[u].size();
            std::vector<int> prefix(m + 1), suffix(m + 1);
            for (int i = 0; i < m; i++) {
                int v = graph[u][i];
                if (v == p) {
                    prefix[i + 1] = std::max(prefix[i], pv.second - std::max(pv.first - 2, 0) - 1);
                } else {
                    prefix[i + 1] = std::max(prefix[i], dp[1][v] - std::max(dp[0][v] - 2, 0) - 1);
                }
            }
            for (int i = m - 1; i >= 0; i--) {
                int v = graph[u][i];
                int j = m - i - 1;
                if (v == p) {
                    suffix[i + 1] = std::max(suffix[i], pv.second - std::max(pv.first - 2, 0) - 1);
                } else {
                    suffix[j + 1] = std::max(suffix[j], dp[1][v] - std::max(dp[0][v] - 2, 0) - 1);
                }
            }
            std::reverse(suffix.begin(), suffix.end());
            for (int i = 0; i < m; i++) {
                int v = graph[u][i];
                if (v == p) continue;
                std::pair<int, int> cv;
                cv.first = now.first - std::max(dp[0][v] - 2, 0);
                cv.second = cv.first + std::max(prefix[i], suffix[i + 1]);
                self(self, v, u, cv);
            }
        };
        dfs(dfs, root, -1, {0, 0});
    }
    std::cout << ans << '\n';
}
accuracy: 0.359375
time_ms: 60
memory_kb: 31512
final_rank: 18

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 0389.cc: Dungeon 2
 */

#include<cstdio>
#include<vector>
#include<algorithm>
 
using namespace std;

/* constant */

const int MAX_N = 100000;
const int INF = 1 << 30;

/* typedef */

typedef vector<int> vi;

/* global variables */

int as[MAX_N], ps[MAX_N], cis[MAX_N];
int ss[MAX_N], xds0[MAX_N], xds1[MAX_N];
int mxs[MAX_N], ts[MAX_N];
vi nbrs[MAX_N];

/* subroutines */

/* main */

int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++) scanf("%d", as + i);

  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    u--, v--;
    nbrs[u].push_back(v);
    nbrs[v].push_back(u);
  }

  ps[0] = -1;
  for (int u = 0; u >= 0;) {
    vi &nbru = nbrs[u];
    int up = ps[u];

    if (cis[u] < nbru.size()) {
      int v = nbru[cis[u]++];
      if (v != up) {
	ps[v] = u;
	u = v;
      }
    }
    else {
      ss[u] += as[u];
      mxs[u] = ss[u] + xds0[u] + xds1[u];

      if (up >= 0) {
	int su = ss[u] - 2;
	int du = xds0[u] + 1;
	if (su > 0) ss[up] += su;
	else du += su;

	if (du > 0) {
	  if (xds0[up] < du) xds1[up] = xds0[up], xds0[up] = du;
	  else if (xds1[up] < du) xds1[up] = du;
	}
      }

      u = up;
    }
  }

  fill(cis, cis + n, 0);
  ts[0] = 0;
  int maxd = -INF;
  for (int u = 0; u >= 0;) {
    vi &nbru = nbrs[u];
    int up = ps[u];

    if (cis[u] < nbru.size()) {
      int v = nbru[cis[u]++];
      if (v != up) {
	int tu = ts[u] + ss[u];
	int tv = tu - (ss[v] > 2 ? ss[v] : 2);
	ts[v] = max(0, tv);
	u = v;
      }
    }
    else {
      maxd = max(maxd, mxs[u] + ts[u]);
      //printf("%d: %d, %d, %d\n", u, mxs[u], ts[u], ss[u]);
      u = up;
    }
  }

  printf("%d\n", maxd);
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 11580
final_rank: 1