題目
先考慮兩棵樹怎麼做。
我們在第二棵樹的每一個點上再掛一個點,他們的距離爲第一棵樹上的。
那麼在第二棵樹上的兩點的距離就是兩棵樹上距離總和-在第一棵樹上的的深度
考慮枚舉這個,那麼答案就應該是的兩個不同子樹,求的在第二棵樹上的的最大值-的深度。
兩個點集間的最長距離的兩個端點一定可以是在兩個點集各自的直徑端點中各取一個。
所以就動態維護點集直徑即可,
時間複雜度
如果的話就是預處理解答
再加入一顆樹。
那麼在第三顆樹上邊分治,把一個點集分成兩個集合,
那麼我們在第一棵樹上建立點集的虛樹,
然後對於第一棵樹和第二棵樹我們用之前的做法不過現在我們要更新答案,
兩個端點不能同在或同在。
簡單一下即可。
時間複雜度
用基排好像可以的理性愉悅一下。
我居然只是小小的調了幾個錯而已。
這代碼比紫荊花之戀和希望都長,應該是我目前最長的代碼了
#include<bits/stdc++.h>
#define maxn 400005
#define LL long long
#define Ct const
#define lim 19
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define ADJ(i,u) for(int i=info[u],v;i;i=Prev[i])
using namespace std;
char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
template<class T>void read(T &res){char ch;for(;!isdigit(ch=getc()););for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');}
int n,lg[maxn];
LL ans;
void PrePare_ST(int MN[lim][maxn],int *dep,int n){ rep(j,1,lim-1)rep(i,0,n-(1<<j)+1)MN[j][i]=dep[MN[j-1][i]]<dep[MN[j-1][i+(1<<j-1)]]?MN[j-1][i]:MN[j-1][i+(1<<j-1)]; }
namespace Tree1{
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
LL dep[maxn],cst[maxn<<1],adep[maxn];
int MN[lim][maxn],ptdep[maxn],st[maxn],dfn;
void Node(int u,int v,LL w){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cst[cnt_e]=w; }
void dfs(int u,int ff){
MN[0][st[u] = ++dfn]=u;
ADJ(i,u) if((v=to[i])^ff) dep[v]=dep[u]+cst[i],ptdep[v]=ptdep[u]+1,dfs(v,u),MN[0][++dfn]=u;
}
void init(){
int u,v;LL w;
rep(i,1,n-1) read(u),read(v),read(w),Node(u,v,w),Node(v,u,w);
}
int LCA(int u,int v){
u = st[u] , v = st[v];
if(u > v) swap(u,v);
int t = lg[v-u+1];
return ptdep[MN[t][u]]<ptdep[MN[t][v-(1<<t)+1]]?MN[t][u]:MN[t][v-(1<<t)+1];
}
LL dis(int u,int v){ if(!u || !v) return 0;u+=n,v+=n; return adep[u] + adep[v] + dep[u] + dep[v] - 2 * dep[LCA(u,v)]; }
}
using Tree1::dis;
int ar[maxn];
namespace Tree2{
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
LL dep[maxn],cst[maxn<<1];
int MN[lim][maxn],ptdep[maxn],st[maxn],col[maxn],dfn;
void Node(int u,int v,LL w){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cst[cnt_e]=w; }
void dfs(int u,int ff){
MN[0][st[u] = ++dfn]=u;Tree1::Node(u,u+n,dep[u]);
ADJ(i,u) if((v=to[i])^ff) dep[v]=dep[u]+cst[i],ptdep[v]=ptdep[u]+1,dfs(v,u),MN[0][++dfn]=u;
}
void init(){
int u,v;LL w;
rep(i,1,n-1) read(u),read(v),read(w),Node(u,v,w),Node(v,u,w);
dfs(1,0);
PrePare_ST(MN,ptdep,dfn);
Tree1::dfs(1,0);
PrePare_ST(Tree1::MN,Tree1::ptdep,Tree1::dfn);
}
int LCA(int u,int v){
u = st[u] , v = st[v];
if(u > v) swap(u,v);
int t = lg[v-u+1];
return ptdep[MN[t][u]]<ptdep[MN[t][v-(1<<t)+1]]?MN[t][u]:MN[t][v-(1<<t)+1];
}
bool cmp(Ct int &u,Ct int &v){ return st[u]<st[v]; }
int f[maxn][2][2];
void merge(int u,int v){
rep(i,0,1) rep(j,0,1) rep(k,0,1)ans = max(ans , dis(f[u][i][j],f[v][i^1][k]) - 2 * dep[u]);
rep(i,0,1){
int a=f[u][i][0],b=f[u][i][1];LL d=dis(a,b),t;
rep(j,0,1) rep(k,0,1) if((t=dis(f[u][i][j],f[v][i][k]))>d || (!a && !b))
d=t,a=f[u][i][j],b=f[v][i][k];
if((t=dis(f[v][i][0],f[v][i][1]))>d || (!a && !b))
d=t,a=f[v][i][0],b=f[v][i][1];
f[u][i][0]=a,f[u][i][1]=b;
}
}
void newnode(int u){
if(!col[u]) f[u][0][0] = f[u][0][1] = f[u][1][0] = f[u][1][1] = 0;
if(col[u] == 1) f[u][0][0] = f[u][0][1] = u , f[u][1][0] = f[u][1][1] = 0;
if(col[u] == 2) f[u][0][0] = f[u][0][1] = 0 , f[u][1][0] = f[u][1][1] = u;
}
void Solve(){
sort(ar+1,ar+1+ar[0],cmp);
static int q[maxn],R=0;
rep(i,1,ar[0]){
if(R){
int t=LCA(q[R],ar[i]),p=0;
for(;R&&ptdep[q[R]]>ptdep[t];p=q[R--]) if(p) merge(q[R],p);
if(q[R]^t) q[++R]=t,newnode(t);
if(p) merge(q[R],p);
}
q[++R]=ar[i],newnode(ar[i]);
}
for(int p=0;R;p=q[R--])
if(p) merge(q[R],p);
}
}
namespace Tree3{
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
LL dep[maxn],cst[maxn<<1],cts[maxn<<1];
void Node(int u,int v,LL w){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cst[cnt_e]=w; }
int fir[maxn],tar[maxn<<1],nxt[maxn<<1],cnte=1;
void add(int u,int v,LL w=0){ nxt[++cnte]=fir[u],fir[u]=cnte,tar[cnte]=v,cts[cnte]=w; }
void lin(int u,int v,LL w=0){ add(u,v,w),add(v,u,w); }
int N,sz[maxn];bool vis[maxn];
void Build(int u,int ff){
int p=0;
ADJ(i,u) if((v=to[i])^ff) Build(v,u),++N,p&&(lin(N,p),0),lin(p=N,v,cst[i]);
if(p) lin(u,p);
}
void dfs(int u,int ff,int tsz,int &mn,int &rt){
sz[u] = 1;
for(int i=fir[u],v;i;i=nxt[i]) if((v=tar[i])^ff && !vis[i]){
dfs(v,u,tsz,mn,rt),sz[u]+=sz[v];
if(max(sz[v],tsz-sz[v]) < mn)
mn = max(sz[v] , tsz-sz[v]) , rt = i;
}
}
int Gert(int u,int tsz){
static int mn,rt;
dfs(u,0,tsz,mn=0x3f3f3f3f,rt=-1);
return rt;
}
void ser(int u,int ff,LL d,int tp){
if(u<=n)
Tree1::adep[u+n] = d,
ar[++ar[0]] = u;
Tree2::col[u] = tp;
sz[u] = 1;
for(int i=fir[u],v;i;i=nxt[i])
if((v=tar[i])^ff && !vis[i]) ser(v,u,d+cts[i],tp),sz[u]+=sz[v];
}
void Solve(int u){
if(u == -1) return;
vis[u] = vis[u^1] = 1;
ar[0] = 0;
ser(tar[u],0,cts[u],1);
ser(tar[u^1],0,0,2);
Tree2::Solve();
Solve(Gert(tar[u],sz[tar[u]])),Solve(Gert(tar[u^1],sz[tar[u^1]]));
}
void init(){
int u,v;LL w;
rep(i,1,n-1) read(u),read(v),read(w),Node(u,v,w),Node(v,u,w);
N=n;Build(1,0);
Solve(Gert(1,N));
}
}
int main(){
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
rep(i,2,maxn-1) lg[i]=lg[i>>1]+1;
scanf("%d",&n);
Tree1::init(),Tree2::init(),Tree3::init();
printf("%lld\n",ans);
}