# [WC2018]通道——边分治+虚树+树形DP

## 题目链接：

[WC2018]通道

### 三、三棵树

#### RMQ求LCA+非递归树形DP

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define pr pair<int,ll>
#define INF 1<<30
int n,m;
int cnt;
int x,y;
ll ans,z;
ll lty[100010];
int col[100010];
struct Miku
{
int x;
ll dep;
}t[400010];
namespace value_tree
{
int tot;
int dfn=0;
ll d[100010];
int s[100010];
ll val[200010];
int lg[200010];
int to[200010];
int next[200010];
ll f[200010][19];
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
f[++dfn][0]=d[x];
s[x]=dfn;
lty[x]+=d[x];
{
if(to[i]!=fa)
{
d[to[i]]=d[x]+val[i];
dfs(to[i],x);
f[++dfn][0]=d[x];
}
}
}
inline void ST()
{
for(int i=2;i<=dfn;i++)
{
lg[i]=lg[i>>1]+1;
}
for(int j=1;j<=18;j++)
{
for(int i=1;i+(1<<j)-1<=dfn;i++)
{
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
inline ll lca(int x,int y)
{
x=s[x],y=s[y];
if(x>y)
{
swap(x,y);
}
int len=lg[y-x+1];
return min(f[x][len],f[y-(1<<len)+1][len]);
}
inline ll dis(int x,int y)
{
return lty[x]+lty[y]-(lca(x,y)<<1);
}
}
namespace virtual_tree
{
int tot;
int num;
int top;
int dfn=0;
int sum=0;
ll mid_edge;
ll d[100010];
int s[100010];
int l[100010];
int r[100010];
int q[200010];
ll val[200010];
int lg[200010];
int to[200010];
int st[200010];
int dep[100010];
int vis[100010];
int next[200010];
int f[200010][19];
struct miku
{
int u,v;
ll len;
miku(){u=0,v=0,len=0;}
miku (const int& U,const int& V){u=U,v=V,len=value_tree::dis(u,v);}
miku (const int& U,const int& V,const ll& L){u=U,v=V,len=L;}
friend bool operator <(miku a,miku b){return a.len<b.len;}
friend miku operator +(miku a,miku b)
{
if(a.u==0)return b;
if(b.u==0)return a;
miku res=max(a,b);
res=max(res,max(miku(a.u,b.v),miku(a.v,b.u)));
res=max(res,max(miku(a.u,b.u),miku(a.v,b.v)));
return res;
}
}dp[100010][2];
bool cmp(int a,int b)
{
int x=a<0?r[-a]:l[a];
int y=b<0?r[-b]:l[b];
return x<y;
}
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
f[++dfn][0]=x;
s[x]=dfn;
l[x]=++sum;
lty[x]+=d[x];
{
if(to[i]!=fa)
{
dep[to[i]]=dep[x]+1;
d[to[i]]=d[x]+val[i];
dfs(to[i],x);
f[++dfn][0]=x;
}
}
r[x]=++sum;
}
inline int mn(int x,int y)
{
return dep[x]<dep[y]?x:y;
}
inline void ST()
{
for(int i=2;i<=dfn;i++)
{
lg[i]=lg[i>>1]+1;
}
for(int j=1;j<=18;j++)
{
for(int i=1;i+(1<<j)-1<=dfn;i++)
{
f[i][j]=mn(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
inline int lca(int x,int y)
{
x=s[x],y=s[y];
if(x>y)
{
swap(x,y);
}
int len=lg[y-x+1];
return mn(f[x][len],f[y-(1<<len)+1][len]);
}
inline ll merge(const miku& a,const miku& b)
{
if(a.u==0||b.u==0)return 0;
return max(max(value_tree::dis(a.u,b.u),value_tree::dis(a.v,b.u)),max(value_tree::dis(a.u,b.v),value_tree::dis(a.v,b.v)));
}
void tree_dp()
{
top=0;
for(int i=1;i<=tot;i++)
{
if(q[i]>0)
{
st[++top]=q[i];
}
else
{
top--;
if(!top)continue;
int fa=st[top];
int x=st[top+1];
ans=max(ans,max(merge(dp[x][0],dp[fa][1]),merge(dp[x][1],dp[fa][0]))+mid_edge-(d[fa]<<1));
dp[fa][0]=dp[fa][0]+dp[x][0];
dp[fa][1]=dp[fa][1]+dp[x][1];
}
}
}
inline void build(ll value)
{
mid_edge=value;
for(int i=1;i<=cnt;i++)
{
vis[t[i].x]=1;
dp[t[i].x][col[t[i].x]-1]=(miku){t[i].x,t[i].x,0};
dp[t[i].x][(col[t[i].x]-1)^1]=(miku){0,0,0};
q[i]=t[i].x;
col[t[i].x]=0;
}
num=tot=cnt;
sort(q+1,q+1+tot,cmp);
for(int i=1;i<num;i++)
{
int fa=lca(q[i],q[i+1]);
if(!vis[fa])
{
vis[fa]=1;
q[++tot]=fa;
dp[fa][0]=dp[fa][1]=(miku){0,0,0};
}
}
for(int i=1;i<=tot;i++)
{
vis[q[i]]=0;
}
num=tot;
for(int i=1;i<=num;i++)
{
q[++tot]=-q[i];
}
sort(q+1,q+1+tot,cmp);
tree_dp();
}
}
namespace edge_partation
{
int tot;
int num;
int root;
int to[800010];
ll val[800010];
int vis[400010];
int next[800010];
int size[400010];
vector<pr>q[400010];
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
{
if(to[i]!=fa)
{
q[x].push_back(make_pair(to[i],val[i]));
dfs(to[i],x);
}
}
}
inline void rebuild()
{
tot=1;
memset(val,0,sizeof(val));
memset(next,0,sizeof(next));
memset(to,0,sizeof(to));
for(int i=1;i<=m;i++)
{
int len=q[i].size();
if(len<=2)
{
for(int j=0;j<len;j++)
{
}
}
else
{
int ls=++m;
int rs=++m;
for(int j=0;j<len;j++)
{
if(j&1)
{
q[ls].push_back(make_pair(q[i][j].first,q[i][j].second));
}
else
{
q[rs].push_back(make_pair(q[i][j].first,q[i][j].second));
}
}
}
}
}
void getroot(int x,int fa,int sum)
{
size[x]=1;
{
if(!vis[i>>1]&&to[i]!=fa)
{
getroot(to[i],x,sum);
size[x]+=size[to[i]];
int mx_size=max(size[to[i]],sum-size[to[i]]);
if(mx_size<num)
{
num=mx_size;
root=i;
}
}
}
}
void dfs2(int x,int fa,ll dep,int opt)
{
if(x<=n)
{
col[x]=opt;
t[++cnt]=(Miku){x,dep};
}
{
if(!vis[i>>1]&&to[i]!=fa)
{
dfs2(to[i],x,dep+val[i],opt);
}
}
}
void partation(int x,int sum)
{
num=INF;
getroot(x,0,sum);
if(num==INF)
{
return ;
}
int now=root;
vis[now>>1]=1;
cnt=0;
dfs2(to[now],0,0ll,1);
dfs2(to[now^1],0,0ll,2);
for(int i=1;i<=cnt;i++)
{
lty[t[i].x]+=t[i].dep;
}
virtual_tree::build(val[now]);
for(int i=1;i<=cnt;i++)
{
lty[t[i].x]-=t[i].dep;
}
int sz=size[to[now]];
partation(to[now],sz);
partation(to[now^1],sum-sz);
}
}
int main()
{
scanf("%d",&n);
m=n;
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}
virtual_tree::dfs(1,0);
virtual_tree::ST();
value_tree::dfs(1,0);
value_tree::ST();
edge_partation::dfs(1,0);
edge_partation::rebuild();
edge_partation::partation(1,m);
printf("%lld",ans);
}

#### RMQ求LCA+递归树形DP

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define pr pair<int,ll>
#define INF 1<<30
int n,m;
int cnt;
int x,y;
ll ans,z;
ll lty[100010];
int col[100010];
struct Miku
{
int x;
ll dep;
}t[400010];
namespace value_tree
{
int tot;
int dfn=0;
ll d[100010];
int s[100010];
ll val[200010];
int lg[200010];
int to[200010];
int next[200010];
ll f[200010][19];
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
f[++dfn][0]=d[x];
s[x]=dfn;
lty[x]+=d[x];
{
if(to[i]!=fa)
{
d[to[i]]=d[x]+val[i];
dfs(to[i],x);
f[++dfn][0]=d[x];
}
}
}
inline void ST()
{
for(int i=2;i<=dfn;i++)
{
lg[i]=lg[i>>1]+1;
}
for(int j=1;j<=18;j++)
{
for(int i=1;i+(1<<j)-1<=dfn;i++)
{
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
inline ll lca(int x,int y)
{
x=s[x],y=s[y];
if(x>y)
{
swap(x,y);
}
int len=lg[y-x+1];
return min(f[x][len],f[y-(1<<len)+1][len]);
}
inline ll dis(int x,int y)
{
return lty[x]+lty[y]-(lca(x,y)<<1);
}
}
namespace virtual_tree
{
int tot;
int top;
int sum=0;
int dfn=0;
ll mid_edge;
ll d[100010];
int l[100010];
int s[100010];
ll val[200010];
int lg[200010];
int to[200010];
int st[100010];
int vis[100010];
int dep[100010];
int next[200010];
int f[200010][19];
vector<int>q[100010];
struct miku
{
int u,v;
ll len;
miku(){u=0,v=0,len=0;}
miku (const int& U,const int& V){u=U,v=V,len=value_tree::dis(u,v);}
miku (const int& U,const int& V,const ll& L){u=U,v=V,len=L;}
friend bool operator <(miku a,miku b){return a.len<b.len;}
friend miku operator +(miku a,miku b)
{
if(a.u==0)return b;
if(b.u==0)return a;
miku res=max(a,b);
res=max(res,max(miku(a.u,b.v),miku(a.v,b.u)));
res=max(res,max(miku(a.u,b.u),miku(a.v,b.v)));
return res;
}
}dp[100010][2];
bool cmp(Miku a,Miku b)
{
return l[a.x]<l[b.x];
}
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
f[++dfn][0]=x;
s[x]=dfn;
l[x]=++sum;
lty[x]+=d[x];
{
if(to[i]!=fa)
{
dep[to[i]]=dep[x]+1;
d[to[i]]=d[x]+val[i];
dfs(to[i],x);
f[++dfn][0]=x;
}
}
}
inline int mn(int x,int y)
{
return dep[x]<dep[y]?x:y;
}
inline void ST()
{
for(int i=2;i<=dfn;i++)
{
lg[i]=lg[i>>1]+1;
}
for(int j=1;j<=18;j++)
{
for(int i=1;i+(1<<j)-1<=dfn;i++)
{
f[i][j]=mn(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
inline int lca(int x,int y)
{
x=s[x],y=s[y];
if(x>y)
{
swap(x,y);
}
int len=lg[y-x+1];
return mn(f[x][len],f[y-(1<<len)+1][len]);
}
inline void insert(int x)
{
int fa=lca(x,st[top]);
if(!vis[fa])
{
vis[fa]=1;
dp[fa][0]=dp[fa][1]=(miku){0,0,0};
}
while(top>1&&dep[st[top-1]]>=dep[fa])
{
q[st[top-1]].push_back(st[top]);
top--;
}
if(fa!=st[top])
{
q[fa].push_back(st[top]);
st[top]=fa;
}
st[++top]=x;
}
inline ll merge(const miku& a,const miku& b)
{
if(a.u==0||b.u==0)return 0;
return max(max(value_tree::dis(a.u,b.u),value_tree::dis(a.v,b.u)),max(value_tree::dis(a.u,b.v),value_tree::dis(a.v,b.v)));
}
void tree_dp(int x)
{
int len=q[x].size();
for(int i=0;i<len;i++)
{
int to=q[x][i];
tree_dp(to);
ans=max(ans,max(merge(dp[x][0],dp[to][1]),merge(dp[x][1],dp[to][0]))+mid_edge-(d[x]<<1));
dp[x][0]=dp[x][0]+dp[to][0];
dp[x][1]=dp[x][1]+dp[to][1];
}
vis[x]=0;
q[x].clear();
}
inline void build(ll value)
{
mid_edge=value;
for(int i=1;i<=cnt;i++)
{
vis[t[i].x]=1;
dp[t[i].x][col[t[i].x]-1]=(miku){t[i].x,t[i].x,0};
dp[t[i].x][(col[t[i].x]-1)^1]=(miku){0,0,0};
col[t[i].x]=0;
}
sort(t+1,t+1+cnt,cmp);
top=0;
if(t[1].x!=1)
{
st[++top]=1;
}
for(int i=1;i<=cnt;i++)
{
insert(t[i].x);
}
while(top>1)
{
q[st[top-1]].push_back(st[top]);
top--;
}
tree_dp(1);
}
}
namespace edge_partation
{
int tot;
int num;
int root;
int to[800010];
ll val[800010];
int vis[400010];
int next[800010];
int size[400010];
vector<pr>q[400010];
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
{
if(to[i]!=fa)
{
q[x].push_back(make_pair(to[i],val[i]));
dfs(to[i],x);
}
}
}
inline void rebuild()
{
tot=1;
for(int i=1;i<=m;i++)
{
int len=q[i].size();
if(len<=2)
{
for(int j=0;j<len;j++)
{
}
}
else
{
int ls=++m;
int rs=++m;
for(int j=0;j<len;j++)
{
if(j&1)
{
q[ls].push_back(make_pair(q[i][j].first,q[i][j].second));
}
else
{
q[rs].push_back(make_pair(q[i][j].first,q[i][j].second));
}
}
}
}
}
void getroot(int x,int fa,int sum)
{
size[x]=1;
{
if(!vis[i>>1]&&to[i]!=fa)
{
getroot(to[i],x,sum);
size[x]+=size[to[i]];
int mx_size=max(size[to[i]],sum-size[to[i]]);
if(mx_size<num)
{
num=mx_size;
root=i;
}
}
}
}
void dfs2(int x,int fa,ll dep,int opt)
{
if(x<=n)
{
col[x]=opt;
t[++cnt]=(Miku){x,dep};
}
{
if(!vis[i>>1]&&to[i]!=fa)
{
dfs2(to[i],x,dep+val[i],opt);
}
}
}
void partation(int x,int sum)
{
num=INF;
getroot(x,0,sum);
if(num==INF)
{
return ;
}
int now=root;
vis[now>>1]=1;
cnt=0;
dfs2(to[now],0,0ll,1);
dfs2(to[now^1],0,0ll,2);
for(int i=1;i<=cnt;i++)
{
lty[t[i].x]+=t[i].dep;
}
virtual_tree::build(val[now]);
for(int i=1;i<=cnt;i++)
{
lty[t[i].x]-=t[i].dep;
}
int sz=size[to[now]];
partation(to[now],sz);
partation(to[now^1],sum-sz);
}
}
int main()
{
scanf("%d",&n);
m=n;
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}
virtual_tree::dfs(1,0);
virtual_tree::ST();
value_tree::dfs(1,0);
value_tree::ST();
edge_partation::dfs(1,0);
edge_partation::rebuild();
edge_partation::partation(1,m);
printf("%lld",ans);
}

#### 树剖求LCA+递归树形DP

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define pr pair<int,ll>
#define INF 1<<30
int n,m;
int cnt;
int x,y;
ll ans,z;
int lg[200010];
ll lty[100010];
int col[100010];
struct Miku
{
int x;
ll dep;
}t[400010];
namespace value_tree
{
int tot;
int dfn;
ll d[100010];
int s[100010];
ll val[200010];
int to[200010];
int next[200010];
ll f[200010][19];
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
f[++dfn][0]=d[x];
s[x]=dfn;
lty[x]+=d[x];
{
if(to[i]!=fa)
{
d[to[i]]=d[x]+val[i];
dfs(to[i],x);
f[++dfn][0]=d[x];
}
}
}
inline void ST()
{
for(int i=2;i<=dfn;i++)
{
lg[i]=lg[i>>1]+1;
}
for(int j=1;j<=18;j++)
{
for(int i=1;i+(1<<j)-1<=dfn;i++)
{
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
inline ll lca(int x,int y)
{
x=s[x],y=s[y];
if(x>y)
{
swap(x,y);
}
int len=lg[y-x+1];
return min(f[x][len],f[y-(1<<len)+1][len]);
}
inline ll dis(int x,int y)
{
return lty[x]+lty[y]-(lca(x,y)<<1);
}
}
namespace virtual_tree
{
int tot;
int top;
int num=0;
ll mid_edge;
ll d[100010];
int f[100010];
int s[100010];
ll val[200010];
int to[200010];
int st[100010];
int vis[100010];
int anc[100010];
int son[100010];
int dep[100010];
int size[100010];
int next[200010];
vector<int>q[100010];
struct miku
{
int u,v;
ll len;
miku(){u=0,v=0,len=0;}
miku (const int& U,const int& V){u=U,v=V,len=value_tree::dis(u,v);}
miku (const int& U,const int& V,const int& L){u=U,v=V,len=L;}
friend bool operator <(miku a,miku b){return a.len<b.len;}
friend miku operator +(miku a,miku b)
{
if(a.u==0)return b;
if(b.u==0)return a;
miku res=max(a,b);
res=max(res,max(miku(a.u,b.v),miku(a.v,b.u)));
res=max(res,max(miku(a.u,b.u),miku(a.v,b.v)));
return res;
}
}dp[100010][2];
bool cmp(Miku a,Miku b)
{
return s[a.x]<s[b.x];
}
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x)
{
dep[x]=dep[f[x]]+1;
size[x]=1;
lty[x]+=d[x];
{
if(to[i]!=f[x])
{
f[to[i]]=x;
d[to[i]]=d[x]+val[i];
dfs(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]])
{
son[x]=to[i];
}
}
}
}
void dfs2(int x,int tp)
{
s[x]=++num;
anc[x]=tp;
if(son[x])
{
dfs2(son[x],tp);
}
{
if(to[i]!=f[x]&&to[i]!=son[x])
{
dfs2(to[i],to[i]);
}
}
}
inline int lca(int x,int y)
{
while(anc[x]!=anc[y])
{
if(dep[anc[x]]<dep[anc[y]])
{
swap(x,y);
}
x=f[anc[x]];
}
return dep[x]<dep[y]?x:y;
}
inline void insert(int x)
{
int fa=lca(x,st[top]);
if(!vis[fa])
{
vis[fa]=1;
dp[fa][0]=dp[fa][1]=(miku){0,0,0};
}
while(top>1&&dep[st[top-1]]>=dep[fa])
{
q[st[top-1]].push_back(st[top]);
top--;
}
if(fa!=st[top])
{
q[fa].push_back(st[top]);
st[top]=fa;
}
st[++top]=x;
}
inline ll merge(const miku& a,const miku& b)
{
if(a.u==0||b.u==0)return 0;
return max(max(value_tree::dis(a.u,b.u),value_tree::dis(a.v,b.u)),max(value_tree::dis(a.u,b.v),value_tree::dis(a.v,b.v)));
}
void tree_dp(int x)
{
int len=q[x].size();
for(int i=0;i<len;i++)
{
int to=q[x][i];
tree_dp(to);
ans=max(ans,max(merge(dp[x][0],dp[to][1]),merge(dp[x][1],dp[to][0]))+mid_edge-2*d[x]);
dp[x][0]=dp[x][0]+dp[to][0];
dp[x][1]=dp[x][1]+dp[to][1];
}
vis[x]=0;
q[x].clear();
}
inline void build(ll value)
{
mid_edge=value;
for(int i=1;i<=cnt;i++)
{
vis[t[i].x]=1;
dp[t[i].x][col[t[i].x]-1]=(miku){t[i].x,t[i].x,0};
dp[t[i].x][(col[t[i].x]-1)^1]=(miku){0,0,0};
col[t[i].x]=0;
}
sort(t+1,t+1+cnt,cmp);
top=0;
if(t[1].x!=1)
{
st[++top]=1;
}
for(int i=1;i<=cnt;i++)
{
insert(t[i].x);
}
while(top>1)
{
q[st[top-1]].push_back(st[top]);
top--;
}
tree_dp(1);
}
}
namespace edge_partation
{
int tot;
int num;
int root;
int to[800010];
ll val[800010];
int vis[400010];
int next[800010];
int size[400010];
vector<pr>q[400010];
inline void add(int x,int y,ll z)
{
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
{
if(to[i]!=fa)
{
q[x].push_back(make_pair(to[i],val[i]));
dfs(to[i],x);
}
}
}
inline void rebuild()
{
tot=1;
for(int i=1;i<=m;i++)
{
int len=q[i].size();
if(len<=2)
{
for(int j=0;j<len;j++)
{
}
}
else
{
int ls=++m;
int rs=++m;
for(int j=0;j<len;j++)
{
if(j&1)
{
q[ls].push_back(make_pair(q[i][j].first,q[i][j].second));
}
else
{
q[rs].push_back(make_pair(q[i][j].first,q[i][j].second));
}
}
}
}
}
void getroot(int x,int fa,int sum)
{
size[x]=1;
{
if(!vis[i>>1]&&to[i]!=fa)
{
getroot(to[i],x,sum);
size[x]+=size[to[i]];
int mx_size=max(size[to[i]],sum-size[to[i]]);
if(mx_size<num)
{
num=mx_size;
root=i;
}
}
}
}
void dfs2(int x,int fa,ll dep,int opt)
{
if(x<=n)
{
col[x]=opt;
t[++cnt]=(Miku){x,dep};
}
{
if(!vis[i>>1]&&to[i]!=fa)
{
dfs2(to[i],x,dep+val[i],opt);
}
}
}
void partation(int x,int sum)
{
num=INF;
getroot(x,0,sum);
if(num==INF)
{
return ;
}
int now=root;
vis[now>>1]=1;
cnt=0;
dfs2(to[now],0,0ll,1);
dfs2(to[now^1],0,0ll,2);
for(int i=1;i<=cnt;i++)
{
lty[t[i].x]+=t[i].dep;
}
virtual_tree::build(val[now]);
for(int i=1;i<=cnt;i++)
{
lty[t[i].x]-=t[i].dep;
}
int sz=size[to[now]];
partation(to[now],sz);
partation(to[now^1],sum-sz);
}
}
int main()
{
scanf("%d",&n);
m=n;
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}
for(int i=1;i<n;i++)
{
scanf("%d%d%lld",&x,&y,&z);
}