我们设初始的那个点为root。则所有的蓝色链都是形如\(father-now-son\)。
我们设计两个dp状态: \(dp_{i,0}\)表示i号点不作为蓝色链的中间点,\(dp_{i,1}\)表示作为中间点。则以下的转移就非常容易了。
\(dp_{i,0}=\sum \max(dp_{u,1}+w,dp_{u,0})\)
\(dp_{i,1}=\sum \max (dp_{u,1}+w,dp_{u,0}) + \max\{dp_{u,0}+w - \max (dp_{u,1}+w,dp_{u,0}) \}\)
换根dp就ok了。
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=200000+20;
int n,rest=-2e9,dp[MAXN][2];
vector<mp> g[MAXN];
void prework(int now,int pre){
int Max=-2e9;
dp[now][0]=0;
for(auto it:g[now]){
int u,w; u=it.FIR,w=it.SEC;
if(u==pre) continue;
prework(u,now);
dp[now][0]+=max(dp[u][1]+w,dp[u][0]);
check_max(Max,dp[u][0]+w-max(dp[u][1]+w,dp[u][0]));
}
dp[now][1]=Max+dp[now][0];
}
void change_root(int now,int pre){
vector<mp> V;
V.PB({-2e9,-1});
dp[now][0]=0;
for(auto it:g[now]){
int u,w; u=it.FIR,w=it.SEC;
dp[now][0]+=max(dp[u][1]+w,dp[u][0]);
V.PB({dp[u][0]+w-max(dp[u][1]+w,dp[u][0]),u});
}
check_max(rest,dp[now][0]);
sort(ALL(V)),reverse(ALL(V));
int old=dp[now][0];
for(auto it:g[now]){
int u=it.FIR,w=it.SEC;
if(u!=pre){
dp[now][0]=old-max(dp[u][1]+w,dp[u][0]);
dp[now][1]=dp[now][0]+(V[0].SEC==u? V[1].FIR:V[0].FIR);
change_root(u,now);
}
}
}
int main(){
scanf("%d",&n);
rb(i,2,n){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
g[a].PB({b,c});
g[b].PB({a,c});
}
prework(1,0);
change_root(1,0);
cout<<rest<<endl;
return 0;
}