Luogu4220 [WC2018]通道
Luogu4220 [WC2018]通道
边分治
考虑如果是两棵树,对一棵树边分治,同时在另一棵树上建虚树统计答案,套路和[CTSC2018]暴力写挂相同。
一开始想不到好的办法,直接对第二棵树的虚树再次边分治,同时在第三棵树上建虚树,统计答案,时间复杂度\(O(n \log^2 n)\)。
结果\(T\)飞了。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100005
#define M 200005
#define ll long long
#define rint register int
#define il inline
using namespace std;
const int INF=1000000007;
const ll LINF=491919191919191919;
int n,x,y,gn;
ll z;
struct node
{
int nxt,v;
ll cost;
il node (int Nxt=0,int D1=0,ll D2=0)
{
nxt=Nxt,v=D1,cost=D2;
}
};
struct edge
{
int tot=0,fr[N];
node e[N << 1];
il void add(int x,int y,ll z)
{
++tot;
e[tot]=node(fr[x],y,z),fr[x]=tot;
}
}T1,T2,T3;
int lg2[N << 1];
struct ST
{
int cnt,ct,dep[N],dfn[N],bg[N],st[N << 1][22];
ll cdp[N];
il int lca(int x,int y)
{
x=bg[x],y=bg[y];
if (x>y)
swap(x,y);
int k=lg2[y-x+1];
return (dep[st[x][k]]<dep[st[y-(1 << k)+1][k]])?st[x][k]:st[y-(1 << k)+1][k];
}
il ll dis(int x,int y)
{
return cdp[x]+cdp[y]-(cdp[lca(x,y)] << 1LL);
}
}s2,s3;
int tot=1,fr[M];
node e[M << 1];
int rt,rtsz,s[N];
int sz[M],col[N],col2[N];
int c[2][N];
ll ans=-LINF,mx,kdp[M];
bool vis[M];
char buf[1 << 23],*p1=buf,*p2=buf,obuf[1 << 23],*O=obuf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1 << 21,stdin),p1==p2)?EOF:*p1++)
il int iread()
{
int s=0;
char c=getchar();
while (c<'0' || c>'9')
c=getchar();
while ('0'<=c && c<='9')
s=(s << 1)+(s << 3)+(c^48),c=getchar();
return s;
}
il ll lread()
{
ll s=0;
char c=getchar();
while (c<'0' || c>'9')
c=getchar();
while ('0'<=c && c<='9')
s=(s << 1)+(s << 3)+(c^48),c=getchar();
return s;
}
template<typename T>
il T cmx(T x,T y)
{
return (x>y)?x:y;
}
il void add(int x,int y,ll z)
{
++tot;
e[tot]=node(fr[x],y,z),fr[x]=tot;
}
il void add_edge(int x,int y,ll z)
{
add(x,y,z),add(y,x,z);
}
il void dfs1(int u,int F)
{
int tt=0,lst;
rint i=T1.fr[u];
if (T1.e[i].v==F)
i=T1.e[i].nxt;
while (i)
{
int v=T1.e[i].v;
ll cost=T1.e[i].cost;
i=T1.e[i].nxt;
if (T1.e[i].v==F)
i=T1.e[i].nxt;
++tt;
if (tt==1)
add_edge(u,v,cost),lst=u; else
if (i)
++gn,add_edge(lst,gn,0),add_edge(gn,v,cost),lst=gn; else
add_edge(lst,v,cost);
dfs1(v,u);
}
}
il void dfs2(int u,int F)
{
s2.dfn[++s2.cnt]=u,s2.st[++s2.ct][0]=u,s2.bg[u]=s2.ct;
for (rint i=T2.fr[u];i;i=T2.e[i].nxt)
{
int v=T2.e[i].v;
ll cost=T2.e[i].cost;
if (v==F)
continue;
s2.cdp[v]=s2.cdp[u]+cost;
s2.dep[v]=s2.dep[u]+1;
dfs2(v,u);
s2.st[++s2.ct][0]=u;
}
}
il void dfs3(int u,int F)
{
s3.dfn[++s3.cnt]=u,s[u]=s3.cnt,s3.st[++s3.ct][0]=u,s3.bg[u]=s3.ct;
for (rint i=T3.fr[u];i;i=T3.e[i].nxt)
{
int v=T3.e[i].v;
ll cost=T3.e[i].cost;
if (v==F)
continue;
s3.cdp[v]=s3.cdp[u]+cost;
s3.dep[v]=s3.dep[u]+1;
dfs3(v,u);
s3.st[++s3.ct][0]=u;
}
}
il void dfs4(int u,int F,int s)
{
sz[u]=1;
for (rint i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
if (v==F || vis[i >> 1])
continue;
dfs4(v,u,s);
sz[u]+=sz[v];
if (cmx(sz[v],s-sz[v])<rtsz)
rtsz=cmx(sz[v],s-sz[v]),rt=i;
}
}
il void dfs5(int u,int F,int opt)
{
if (u<=n)
col[u]=opt;
for (rint i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
ll cost=e[i].cost;
if (v==F || vis[i >> 1])
continue;
kdp[v]=kdp[u]+cost;
dfs5(v,u,opt);
}
}
namespace BT
{
int gn,tot=1,q[N],fr[M];
int sz[M];
ll val[M],kdp[M];
node e[M << 1];
bool vis[M];
};
namespace VT3
{
int tot,fr[N];
node e[N << 1];
int t,st[N];
ll dp[2][2][N];
il void add(int x,int y)
{
++tot;
e[tot]=node(fr[x],y),fr[x]=tot;
}
il void ins(int x)
{
if (!t)
{
st[++t]=x;
return;
}
int g=s3.lca(x,st[t]);
while (t>1 && s3.dep[g]<s3.dep[st[t-1]])
add(st[t-1],st[t]),--t;
if (s3.dep[g]<s3.dep[st[t]])
add(g,st[t]),t--;
if (!t || st[t]!=g)
st[++t]=g;
st[++t]=x;
}
il void dfs8(int u)
{
dp[0][0][u]=dp[0][1][u]=dp[1][0][u]=dp[1][1][u]=-LINF;
if (u<=n && col[u]>=0 && col2[u]>=0)
dp[col[u]][col2[u]][u]=BT::val[u];
for (rint i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
dfs8(v);
ans=cmx(ans,dp[0][0][u]+dp[1][1][v]-(s3.cdp[u] << 1LL));
ans=cmx(ans,dp[0][1][u]+dp[1][0][v]-(s3.cdp[u] << 1LL));
ans=cmx(ans,dp[0][0][v]+dp[1][1][u]-(s3.cdp[u] << 1LL));
ans=cmx(ans,dp[0][1][v]+dp[1][0][u]-(s3.cdp[u] << 1LL));
dp[0][0][u]=cmx(dp[0][0][u],dp[0][0][v]);
dp[0][1][u]=cmx(dp[0][1][u],dp[0][1][v]);
dp[1][0][u]=cmx(dp[1][0][u],dp[1][0][v]);
dp[1][1][u]=cmx(dp[1][1][u],dp[1][1][v]);
}
}
il void Clear(int u)
{
col2[u]=-1;
for (rint i=fr[u];i;i=e[i].nxt)
Clear(e[i].v);
fr[u]=0;
}
};
namespace VT2
{
int ct=0,dfn[N];
};
namespace BT
{
int rtsz,rt;
il void add(int x,int y,ll z)
{
++tot;
e[tot]=node(fr[x],y,z),fr[x]=tot;
}
il void add_edge(int x,int y,ll z)
{
add(x,y,z),add(y,x,z);
}
il void dfs4(int u,int F,int s)
{
sz[u]=1;
for (rint i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
ll cost=e[i].cost;
if (v==F || vis[i >> 1])
continue;
dfs4(v,u,s);
sz[u]+=sz[v];
if (cmx(sz[v],s-sz[v])<rtsz)
rtsz=cmx(sz[v],s-sz[v]),rt=i;
}
}
il void dfs5(int u,int F,int opt)
{
if (col[u]>=0 && u<=n)
col2[u]=opt,val[u]=::kdp[u]+kdp[u]+s3.cdp[u];
for (rint i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
ll cost=e[i].cost;
if (v==F || vis[i >> 1])
continue;
kdp[v]=kdp[u]+cost;
dfs5(v,u,opt);
}
}
il void Clear(int u,int F)
{
for (rint i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
if (v==F)
continue;
Clear(v,u);
}
fr[u]=0;
}
};
namespace VT
{
int tot,fr[N];
node e[N << 1];
int t,st[N],c[2][N];
il void add(int x,int y,ll z)
{
++tot;
e[tot]=node(fr[x],y,z),fr[x]=tot;
}
il void ins(int x)
{
if (!t)
{
st[++t]=x;
return;
}
int g=s2.lca(x,st[t]);
while (t>1 && s2.dep[g]<s2.dep[st[t-1]])
add(st[t-1],st[t],s2.dis(st[t-1],st[t])),--t;
if (s2.dep[g]<s2.dep[st[t]])
add(g,st[t],s2.dis(g,st[t])),t--;
if (!t || st[t]!=g)
st[++t]=g;
st[++t]=x;
}
il void dfs6(int u,int F)
{
int tt=0,lst;
rint i=fr[u];
if (e[i].v==F)
i=e[i].nxt;
while (i)
{
int v=e[i].v;
ll cost=e[i].cost;
i=e[i].nxt;
if (e[i].v==F)
i=e[i].nxt;
++tt;
if (tt==1)
BT::add_edge(u,v,cost),lst=u; else
if (i)
++BT::gn,BT::add_edge(lst,BT::gn,0),BT::add_edge(BT::gn,v,cost),lst=BT::gn; else
BT::add_edge(lst,v,cost);
dfs6(v,u);
}
}
il void solve(int u,int s,int l,int r)
{
if (l>=r)
return;
BT::rtsz=INF;
BT::dfs4(u,0,s);
if (BT::rtsz==INF)
return;
BT::vis[BT::rt >> 1]=true;
BT::kdp[BT::e[BT::rt].v]=0,BT::kdp[BT::e[BT::rt^1].v]=BT::e[BT::rt].cost;
BT::dfs5(BT::e[BT::rt].v,0,0),BT::dfs5(BT::e[BT::rt^1].v,0,1);
VT3::t=0;
for (rint i=l;i<=r;++i)
VT3::ins(VT2::dfn[i]);
for (rint i=2;i<=VT3::t;++i)
VT3::add(VT3::st[i-1],VT3::st[i]);
VT3::dfs8(VT3::st[1]);
c[0][0]=c[1][0]=0;
for (rint i=l;i<=r;++i)
c[col2[VT2::dfn[i]]][++c[col2[VT2::dfn[i]]][0]]=VT2::dfn[i];
VT3::Clear(VT3::st[1]);
VT3::tot=0;
int L=l-1;
for (rint j=1;j<=c[0][0];++j)
VT2::dfn[++L]=c[0][j];
for (rint j=1;j<=c[1][0];++j)
VT2::dfn[++L]=c[1][j];
int k=BT::rt,ts=s-BT::sz[BT::e[k].v],mid=l+c[0][0]-1;
solve(BT::e[k].v,BT::sz[BT::e[k].v],l,mid),solve(BT::e[k^1].v,ts,mid+1,r);
BT::vis[k >> 1]=false;
}
il void calc(int s)
{
int u=st[1];
BT::gn=n;
dfs6(u,0);
solve(st[1],BT::gn-n+s,1,s);
BT::Clear(u,0),BT::tot=1;
}
il void Clear(int u)
{
col[u]=-1;
for (rint i=fr[u];i;i=e[i].nxt)
Clear(e[i].v);
fr[u]=0;
}
};
il void solve(int u,int s,int l,int r)
{
if (l>=r)
return;
rtsz=INF;
dfs4(u,0,s);
if (rtsz==INF)
return;
vis[rt >> 1]=true;
kdp[e[rt].v]=0,kdp[e[rt^1].v]=e[rt].cost;
dfs5(e[rt].v,0,0),dfs5(e[rt^1].v,0,1);
VT::t=0;
for (rint i=l;i<=r;++i)
VT::ins(s2.dfn[i]);
for (rint i=2;i<=VT::t;++i)
VT::add(VT::st[i-1],VT::st[i],s2.dis(VT::st[i-1],VT::st[i]));
memcpy(VT2::dfn+1,s3.dfn+l,(r-l+1)*sizeof(int));
VT::calc(r-l+1);
c[0][0]=c[1][0]=0;
for (rint i=l;i<=r;++i)
c[col[s2.dfn[i]]][++c[col[s2.dfn[i]]][0]]=s2.dfn[i];
int L=l-1;
for (rint j=1;j<=c[0][0];++j)
s2.dfn[++L]=c[0][j];
for (rint j=1;j<=c[1][0];++j)
s2.dfn[++L]=c[1][j];
c[0][0]=c[1][0]=0;
for (rint i=l;i<=r;++i)
c[col[s3.dfn[i]]][++c[col[s3.dfn[i]]][0]]=s3.dfn[i];
L=l-1;
for (rint j=1;j<=c[0][0];++j)
s3.dfn[++L]=c[0][j];
for (rint j=1;j<=c[1][0];++j)
s3.dfn[++L]=c[1][j];
VT::Clear(VT::st[1]),VT::tot=0;
int k=rt,ts=s-sz[e[k].v],mid=l+c[0][0]-1;
solve(e[k].v,sz[e[k].v],l,mid),solve(e[k^1].v,ts,mid+1,r);
}
int main()
{
n=iread(),gn=n;
for (rint i=1;i<n;++i)
{
x=iread(),y=iread(),z=lread();
T1.add(x,y,z),T1.add(y,x,z);
}
dfs1(1,0);
for (rint i=1;i<n;++i)
{
x=iread(),y=iread(),z=lread();
T2.add(x,y,z),T2.add(y,x,z);
}
s2.dep[1]=1,s2.cdp[1]=0,dfs2(1,0);
lg2[0]=-1;
for (rint i=1;i<=s2.ct;++i)
lg2[i]=lg2[i >> 1]+1;
for (rint j=1;j<=lg2[s2.ct];++j)
for (rint i=1;i<=s2.ct-(1 << j)+1;++i)
s2.st[i][j]=(s2.dep[s2.st[i][j-1]]<s2.dep[s2.st[i+(1 << j-1)][j-1]])?s2.st[i][j-1]:s2.st[i+(1 << j-1)][j-1];
for (rint i=1;i<n;++i)
{
x=iread(),y=iread(),z=lread();
T3.add(x,y,z),T3.add(y,x,z);
}
s3.dep[1]=1,s3.cdp[1]=0,dfs3(1,0);
for (rint j=1;j<=lg2[s3.ct];++j)
for (rint i=1;i<=s3.ct-(1 << j)+1;++i)
s3.st[i][j]=(s3.dep[s3.st[i][j-1]]<s3.dep[s3.st[i+(1 << j-1)][j-1]])?s3.st[i][j-1]:s3.st[i+(1 << j-1)][j-1];
for (rint i=1;i<=n;++i)
col[i]=col2[i]=-1;
solve(1,gn,1,n);
printf("%lld\n",ans);
return 0;
}
设第一棵树的边分树中,分治得的两棵子树,其中的节点\(u\)的深度为\(dep'(u)\)。
可以考虑树上最长路径的性质,如果有两个点集在树上的直径分别为\((u_1,v_1)\)和\((u_2,v_2)\),那么把这两个点集合并后,新点集的直径必然为\((u_1,v_1),(u_1,v_2),(u_2,v_1),(u_2,v_2)\)其中之一。
那么我们同样在第二棵树的\(lca\)处统计答案,维护子树黑色点集和白色点集,互相合并,同时让直径带上权,为\(dep'(u)+dep2(u)\),用同色点集合并直径,用异色点集统计答案。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100005
#define M 200005
#define ll long long
#define rint register int
#define il inline
using namespace std;
const int INF=1000000007;
const ll LINF=491919191919191919;
int n,x,y,gn;
ll z;
struct node
{
int nxt,v;
ll cost;
il node (int Nxt=0,int D1=0,ll D2=0)
{
nxt=Nxt,v=D1,cost=D2;
}
};
struct edge
{
int tot=0,fr[N];
node e[N << 1];
il void add(int x,int y,ll z)
{
++tot;
e[tot]=node(fr[x],y,z),fr[x]=tot;
}
}T1,T2,T3;
int lg2[N << 1];
struct ST
{
int cnt,ct,dep[N],dfn[N],bg[N],st[N << 1][22];
ll cdp[N];
il int lca(int x,int y)
{
x=bg[x],y=bg[y];
if (x>y)
swap(x,y);
int k=lg2[y-x+1];
return (dep[st[x][k]]<dep[st[y-(1 << k)+1][k]])?st[x][k]:st[y-(1 << k)+1][k];
}
il ll dis(int x,int y)
{
return cdp[x]+cdp[y]-(cdp[lca(x,y)] << 1LL);
}
}s2,s3;
int tot=1,fr[M];
node e[M << 1];
int rt,rtsz,s[N];
int sz[M],col[N];
int c[2][N];
ll ans=-LINF,mx,kdp[M],val[N];
bool vis[M];
char buf[1 << 23],*p1=buf,*p2=buf,obuf[1 << 23],*O=obuf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1 << 21,stdin),p1==p2)?EOF:*p1++)
il int iread()
{
int s=0;
char c=getchar();
while (c<'0' || c>'9')
c=getchar();
while ('0'<=c && c<='9')
s=(s << 1)+(s << 3)+(c^48),c=getchar();
return s;
}
il ll lread()
{
ll s=0;
char c=getchar();
while (c<'0' || c>'9')
c=getchar();
while ('0'<=c && c<='9')
s=(s << 1)+(s << 3)+(c^48),c=getchar();
return s;
}
template<typename T>
il T cmx(T x,T y)
{
return (x>y)?x:y;
}
il void add(int x,int y,ll z)
{
++tot;
e[tot]=node(fr[x],y,z),fr[x]=tot;
}
il void add_edge(int x,int y,ll z)
{
add(x,y,z),add(y,x,z);
}
il void dfs1(int u,int F)
{
int tt=0,lst;
rint i=T1.fr[u];
if (T1.e[i].v==F)
i=T1.e[i].nxt;
while (i)
{
int v=T1.e[i].v;
ll cost=T1.e[i].cost;
i=T1.e[i].nxt;
if (T1.e[i].v==F)
i=T1.e[i].nxt;
++tt;
if (tt==1)
add_edge(u,v,cost),lst=u; else
if (i)
++gn,add_edge(lst,gn,0),add_edge(gn,v,cost),lst=gn; else
add_edge(lst,v,cost);
dfs1(v,u);
}
}
il void dfs2(int u,int F)
{
s2.dfn[++s2.cnt]=u,s2.st[++s2.ct][0]=u,s2.bg[u]=s2.ct;
for (rint i=T2.fr[u];i;i=T2.e[i].nxt)
{
int v=T2.e[i].v;
ll cost=T2.e[i].cost;
if (v==F)
continue;
s2.cdp[v]=s2.cdp[u]+cost;
s2.dep[v]=s2.dep[u]+1;
dfs2(v,u);
s2.st[++s2.ct][0]=u;
}
}
il void dfs3(int u,int F)
{
s3.dfn[++s3.cnt]=u,s[u]=s3.cnt,s3.st[++s3.ct][0]=u,s3.bg[u]=s3.ct;
for (rint i=T3.fr[u];i;i=T3.e[i].nxt)
{
int v=T3.e[i].v;
ll cost=T3.e[i].cost;
if (v==F)
continue;
s3.cdp[v]=s3.cdp[u]+cost;
s3.dep[v]=s3.dep[u]+1;
dfs3(v,u);
s3.st[++s3.ct][0]=u;
}
}
il void dfs4(int u,int F,int s)
{
sz[u]=1;
for (rint i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
if (v==F || vis[i >> 1])
continue;
dfs4(v,u,s);
sz[u]+=sz[v];
if (cmx(sz[v],s-sz[v])<rtsz)
rtsz=cmx(sz[v],s-sz[v]),rt=i;
}
}
il void dfs5(int u,int F,int opt)
{
if (u<=n)
col[u]=opt,val[u]=kdp[u]+s2.cdp[u];
for (rint i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
ll cost=e[i].cost;
if (v==F || vis[i >> 1])
continue;
kdp[v]=kdp[u]+cost;
dfs5(v,u,opt);
}
}
il void ckmx(ll &x,ll y)
{
x=(x>y)?x:y;
}
struct DpNode
{
ll s;
int x,y;
DpNode (ll S=0,int X=0,int Y=0)
{
s=S,x=X,y=Y;
}
};
namespace VT
{
int tot,fr[N];
node e[N << 1];
int t,st[N];
DpNode dp[N][2];
DpNode DINF=DpNode(-INF,-1,-1);
il void add(int x,int y)
{
++tot;
e[tot]=node(fr[x],y),fr[x]=tot;
}
il void ins(int x)
{
if (!t)
{
st[++t]=x;
return;
}
int g=s2.lca(x,st[t]);
while (t>1 && s2.dep[g]<s2.dep[st[t-1]])
add(st[t-1],st[t]),--t;
if (s2.dep[g]<s2.dep[st[t]])
add(g,st[t]),t--;
if (!t || st[t]!=g)
st[++t]=g;
st[++t]=x;
}
il void dfs6(int u)
{
dp[u][0]=dp[u][1]=DINF;
if (u<=n && col[u]!=-1)
dp[u][col[u]]=DpNode(val[u],u,u);
for (int i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
dfs6(v);
ckmx(ans,s3.dis(dp[u][0].x,dp[v][1].x)+val[dp[u][0].x]+val[dp[v][1].x]-(s2.cdp[u] << 1LL));
ckmx(ans,s3.dis(dp[u][0].x,dp[v][1].y)+val[dp[u][0].x]+val[dp[v][1].y]-(s2.cdp[u] << 1LL));
ckmx(ans,s3.dis(dp[u][0].y,dp[v][1].x)+val[dp[u][0].y]+val[dp[v][1].x]-(s2.cdp[u] << 1LL));
ckmx(ans,s3.dis(dp[u][0].y,dp[v][1].y)+val[dp[u][0].y]+val[dp[v][1].y]-(s2.cdp[u] << 1LL));
ckmx(ans,s3.dis(dp[u][1].x,dp[v][0].x)+val[dp[u][1].x]+val[dp[v][0].x]-(s2.cdp[u] << 1LL));
ckmx(ans,s3.dis(dp[u][1].x,dp[v][0].y)+val[dp[u][1].x]+val[dp[v][0].y]-(s2.cdp[u] << 1LL));
ckmx(ans,s3.dis(dp[u][1].y,dp[v][0].x)+val[dp[u][1].y]+val[dp[v][0].x]-(s2.cdp[u] << 1LL));
ckmx(ans,s3.dis(dp[u][1].y,dp[v][0].y)+val[dp[u][1].y]+val[dp[v][0].y]-(s2.cdp[u] << 1LL));
if (s3.dis(dp[u][0].x,dp[v][0].x)+val[dp[u][0].x]+val[dp[v][0].x]>dp[u][0].s)
dp[u][0]=DpNode(s3.dis(dp[u][0].x,dp[v][0].x)+val[dp[u][0].x]+val[dp[v][0].x],dp[u][0].x,dp[v][0].x);
if (s3.dis(dp[u][0].x,dp[v][0].y)+val[dp[u][0].x]+val[dp[v][0].y]>dp[u][0].s)
dp[u][0]=DpNode(s3.dis(dp[u][0].x,dp[v][0].y)+val[dp[u][0].x]+val[dp[v][0].y],dp[u][0].x,dp[v][0].y);
if (s3.dis(dp[u][0].y,dp[v][0].x)+val[dp[u][0].y]+val[dp[v][0].x]>dp[u][0].s)
dp[u][0]=DpNode(s3.dis(dp[u][0].y,dp[v][0].x)+val[dp[u][0].y]+val[dp[v][0].x],dp[u][0].y,dp[v][0].x);
if (s3.dis(dp[u][0].y,dp[v][0].y)+val[dp[u][0].y]+val[dp[v][0].y]>dp[u][0].s)
dp[u][0]=DpNode(s3.dis(dp[u][0].y,dp[v][0].y)+val[dp[u][0].y]+val[dp[v][0].y],dp[u][0].y,dp[v][0].y);
if (s3.dis(dp[u][1].x,dp[v][1].x)+val[dp[u][1].x]+val[dp[v][1].x]>dp[u][1].s)
dp[u][1]=DpNode(s3.dis(dp[u][1].x,dp[v][1].x)+val[dp[u][1].x]+val[dp[v][1].x],dp[u][1].x,dp[v][1].x);
if (s3.dis(dp[u][1].x,dp[v][1].y)+val[dp[u][1].x]+val[dp[v][1].y]>dp[u][1].s)
dp[u][1]=DpNode(s3.dis(dp[u][1].x,dp[v][1].y)+val[dp[u][1].x]+val[dp[v][1].y],dp[u][1].x,dp[v][1].y);
if (s3.dis(dp[u][1].y,dp[v][1].x)+val[dp[u][1].y]+val[dp[v][1].x]>dp[u][1].s)
dp[u][1]=DpNode(s3.dis(dp[u][1].y,dp[v][1].x)+val[dp[u][1].y]+val[dp[v][1].x],dp[u][1].y,dp[v][1].x);
if (s3.dis(dp[u][1].y,dp[v][1].y)+val[dp[u][1].y]+val[dp[v][1].y]>dp[u][1].s)
dp[u][1]=DpNode(s3.dis(dp[u][1].y,dp[v][1].y)+val[dp[u][1].y]+val[dp[v][1].y],dp[u][1].y,dp[v][1].y);
}
}
il void Clear(int u)
{
col[u]=-1,val[u]=-LINF;
for (rint i=fr[u];i;i=e[i].nxt)
Clear(e[i].v);
fr[u]=0;
}
};
il void solve(int u,int s,int l,int r)
{
if (l>=r)
return;
rtsz=INF;
dfs4(u,0,s);
if (rtsz==INF)
return;
vis[rt >> 1]=true;
kdp[e[rt].v]=0,kdp[e[rt^1].v]=e[rt].cost;
dfs5(e[rt].v,0,0),dfs5(e[rt^1].v,0,1);
VT::t=0;
for (rint i=l;i<=r;++i)
VT::ins(s2.dfn[i]);
for (rint i=2;i<=VT::t;++i)
VT::add(VT::st[i-1],VT::st[i]);
VT::dfs6(VT::st[1]);
c[0][0]=c[1][0]=0;
for (rint i=l;i<=r;++i)
c[col[s2.dfn[i]]][++c[col[s2.dfn[i]]][0]]=s2.dfn[i];
int L=l-1;
for (rint j=1;j<=c[0][0];++j)
s2.dfn[++L]=c[0][j];
for (rint j=1;j<=c[1][0];++j)
s2.dfn[++L]=c[1][j];
VT::Clear(VT::st[1]),VT::tot=0;
int k=rt,ts=s-sz[e[k].v],mid=l+c[0][0]-1;
solve(e[k].v,sz[e[k].v],l,mid),solve(e[k^1].v,ts,mid+1,r);
}
int main()
{
n=iread(),gn=n;
for (rint i=1;i<n;++i)
{
x=iread(),y=iread(),z=lread();
T1.add(x,y,z),T1.add(y,x,z);
}
dfs1(1,0);
for (rint i=1;i<n;++i)
{
x=iread(),y=iread(),z=lread();
T2.add(x,y,z),T2.add(y,x,z);
}
s2.dep[1]=1,s2.cdp[1]=0,dfs2(1,0);
lg2[0]=-1;
for (rint i=1;i<=s2.ct;++i)
lg2[i]=lg2[i >> 1]+1;
for (rint j=1;j<=lg2[s2.ct];++j)
for (rint i=1;i<=s2.ct-(1 << j)+1;++i)
s2.st[i][j]=(s2.dep[s2.st[i][j-1]]<s2.dep[s2.st[i+(1 << j-1)][j-1]])?s2.st[i][j-1]:s2.st[i+(1 << j-1)][j-1];
for (rint i=1;i<n;++i)
{
x=iread(),y=iread(),z=lread();
T3.add(x,y,z),T3.add(y,x,z);
}
s3.dep[1]=1,s3.cdp[1]=0,dfs3(1,0);
for (rint j=1;j<=lg2[s3.ct];++j)
for (rint i=1;i<=s3.ct-(1 << j)+1;++i)
s3.st[i][j]=(s3.dep[s3.st[i][j-1]]<s3.dep[s3.st[i+(1 << j-1)][j-1]])?s3.st[i][j-1]:s3.st[i+(1 << j-1)][j-1];
for (rint i=1;i<=n;++i)
col[i]=-1;
solve(1,gn,1,n);
printf("%lld\n",ans);
return 0;
}