版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82944203
题解:
按照套路,变成求
然后除个二。
在第二棵树里面做,相当于支持一下不同子树内部点距离的最大值。
可以边分治,然后就跟线段树结构一样了,合并成了 ,代码是真的好写。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair <int,LL> pii;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=8e5;
const LL INF=1e17;
int n,tot,cnt,total,mx,stx,sty,stl;
LL dep[N],ans=-INF; int bl[N],sze[N],vs;
int rt[N],lc[N*20],rc[N*20],*pos[N];
LL lmax[N*20],rmax[N*20];
vector <pii> e1[N];
vector <pii> e2[N];
vector <pii> e3[N];
inline void add(vector <pii> *e,int x,int y,int w) {e[x].push_back(pii(y,w)); e[y].push_back(pii(x,w));}
inline void dfs1(int x,int f,LL dp) {
dep[x]=dp;
vector <pii> vec;
for(auto v:e1[x]) if(v.first^f)
dfs1(v.first,x,dp+v.second), vec.push_back(v);
for(int j=0;j<vec.size();++j) {
++tot; add(e2,tot,vec[j].first,vec[j].second);
if(j) add(e2,tot,tot-1,0);
else add(e2,x,tot,0);
}
}
inline void calcG(int x,int f) {
sze[x]=1;
for(auto v:e2[x]) if(v.first^f && bl[x]==bl[v.first]) {
calcG(v.first,x), sze[x]+=sze[v.first];
int mx_son=max(sze[v.first],total-sze[v.first]);
if(mx>=mx_son) mx=mx_son, stx=x, sty=v.first, stl=v.second;
}
}
inline void dfs2(int x,int f,LL dp,int tar) {
sze[x]=1;
if(x<=n) {
*pos[x]=++cnt;
(tar ? rmax[*pos[x]] : lmax[*pos[x]])=dp+dep[x];
(tar ? lmax[*pos[x]] : rmax[*pos[x]])=-INF;
pos[x]=&(tar ? rc[*pos[x]] : lc[*pos[x]]);
}
for(auto v:e2[x]) if(v.first^f && bl[v.first]==bl[x]) {
dfs2(v.first,x,dp+v.second,tar);
sze[x]+=sze[v.first];
}
bl[x]=vs;
}
inline void solve(int x,int y) {
++vs; dfs2(x,y,0,0);
++vs; dfs2(y,x,stl,1);
if(sze[x]>1) {
total=mx=sze[x];
calcG(x,y);
solve(stx,sty);
}
if(sze[y]>1) {
total=mx=sze[y];
calcG(y,x);
solve(stx,sty);
}
}
LL base;
inline int merge(int x,int y) {
if(!x || !y) return x+y;
ans=max(ans,lmax[x]+rmax[y]+base);
ans=max(ans,lmax[y]+rmax[x]+base);
lmax[x]=max(lmax[x],lmax[y]);
rmax[x]=max(rmax[x],rmax[y]);
lc[x]=merge(lc[x],lc[y]);
rc[x]=merge(rc[x],rc[y]);
return x;
}
inline void dfs3(int x,int f,LL dp) {
ans=max(ans,2*dep[x]-2*dp);
for(auto v:e3[x]) if(v.first^f) {
dfs3(v.first,x,dp+v.second);
base=-2*dp;
rt[x]=merge(rt[x],rt[v.first]);
}
}
int main() {
n=rd(); tot=n;
for(int i=1;i<n;i++) {
int x=rd(), y=rd(), w=rd();
add(e1,x,y,w);
}
dfs1(1,0,0);
for(int i=1;i<=n;i++) pos[i]=&rt[i];
total=mx=tot;
calcG(1,0);
solve(stx,sty);
for(int i=1;i<n;i++) {
int x=rd(), y=rd(), w=rd();
add(e3,x,y,w);
}
dfs3(1,0,0);
cout<<ans/2<<'\n';
}