#include "bits/stdc++.h"
using namespace std;
#define MAXN 330000
struct EDGE{
int Next,To;
}E[MAXN*2];
int Head[2*MAXN],Size;
inline void Add(int From,int To){
E[++Size].Next=Head[From];
Head[From]=Size;
E[Size].To=To;
return;
}
int Fa[MAXN],Tot[MAXN];
int Son[MAXN],Dep[MAXN];
inline void DFS1(int This,int F){
Fa[This]=F;
Tot[This]=1;
int MaxSon=0;
Dep[This]=Dep[F]+1;
for(register int i=Head[This];i;i=E[i].Next){
int To=E[i].To;
if(To==F)continue;
DFS1(To,This);
Tot[This]+=Tot[To];
if(Tot[To]>MaxSon){
MaxSon=Tot[To];
Son[This]=To;
}
}
return;
}
int A[MAXN],InPut[MAXN];
int Count,ID[MAXN],Top[MAXN];
inline void DFS2(int This,int Topf){
Top[This]=Topf;
ID[This]=(++Count);
InPut[Count]=A[This];
if(Son[This]==0)
return;
DFS2(Son[This],Topf);
for(register int i=Head[This];i;i=E[i].Next){
int To=E[i].To;
if(To==Son[This]||To==Fa[This])
continue;
DFS2(To,To);
}
return;
}
struct SegmentTree{
int Lazy,Max,Sum;
int Left,Right;
}Tree[MAXN*4];
inline int LeftSon(int i){return i<<1;}
inline int RightSon(int i){return i<<1|1;}
inline void Build(int Left,int Right,int i){
Tree[i].Left=Left;
Tree[i].Right=Right;
if(Left==Right){
Tree[i].Sum=InPut[Left];
return;
}
int Mid=(Left+Right)>>1;
int L=LeftSon(i),R=RightSon(i);
Build(Left,Mid,L),Build(Mid+1,Right,R);
Tree[i].Sum=Tree[L].Sum+Tree[R].Sum;
return;
}
inline void PushDown(int i){
if(Tree[i].Lazy==0)
return;
int Compare=Tree[i].Lazy;
int L=LeftSon(i),R=RightSon(i);
Tree[L].Lazy=max(Tree[L].Lazy,Compare);
Tree[R].Lazy=max(Tree[R].Lazy,Compare);
Tree[L].Max=max(Tree[L].Max,Compare);
Tree[R].Max=max(Tree[R].Max,Compare);
Tree[i].Lazy=0;
return;
}
inline int SumSeg(int i,int Left,int Right){
if(Left>Right)return 0;
if(Tree[i].Left>Right||Left>Tree[i].Right)
return 0;
if(Left<=Tree[i].Left&&Tree[i].Right<=Right)
return Tree[i].Sum;
PushDown(i);
int Sum=0,L=LeftSon(i),R=RightSon(i);
if(Tree[L].Right>=Left)Sum+=SumSeg(L,Left,Right);
if(Tree[R].Left<=Right)Sum+=SumSeg(R,Left,Right);
return Sum;
}
inline int MaxSeg(int i,int W){
if(Tree[i].Left>W||W>Tree[i].Right)
return 0;
if(Tree[i].Left==Tree[i].Right)
return Tree[i].Max;
PushDown(i);
int Max=0;
int L=LeftSon(i),R=RightSon(i);
if(Tree[L].Right>=W)Max=max(Max,MaxSeg(L,W));
if(Tree[R].Left<=W)Max=max(Max,MaxSeg(R,W));
return Max;
}
inline void CloSeg(int i,int Left,int Right,int C){
if(Left>Right)return;
if(Left>Tree[i].Right||Tree[i].Left>Right)
return;
if(Left<=Tree[i].Left&&Tree[i].Right<=Right){
Tree[i].Lazy=max(Tree[i].Lazy,C);
Tree[i].Max=max(Tree[i].Max,C);
return;
}
PushDown(i);
int L=LeftSon(i),R=RightSon(i);
if(Tree[L].Right>=Left)CloSeg(L,Left,Right,C);
if(Tree[R].Left<=Right)CloSeg(R,Left,Right,C);
Tree[i].Max=max(Tree[L].Max,Tree[R].Max);
return;
}
inline int SumTree(int X,int Y){
int Sum=0;
while(Top[X]!=Top[Y]){
if(Dep[Top[X]]<Dep[Top[Y]])
swap(X,Y);
Sum+=SumSeg(1,ID[Top[X]],ID[X]);
X=Fa[Top[X]];
}
if(X==Y)return Sum;
if(Dep[X]>Dep[Y])
swap(X,Y);
Sum+=SumSeg(1,ID[Son[X]],ID[Y]);
return Sum;
}
int N,M;
inline void Clover(int X,int Y,int Z){
if(Dep[X]<Dep[Y])
swap(X,Y);
CloSeg(1,ID[X]+1,ID[X]+Tot[X]-1,Z);
if(Top[X]!=Top[Y])
CloSeg(1,ID[Y]+1,ID[Y]+Tot[Y]-1,Z);
while(Top[X]!=Top[Y]){
if(Dep[Top[X]]<Dep[Top[Y]])
swap(X,Y);
CloSeg(1,ID[X]+Tot[X],ID[Top[X]]+Tot[Top[X]]-1,Z);
X=Fa[Top[X]];
}
if(X==Y)return;
if(Dep[X]>Dep[Y])swap(X,Y);
CloSeg(1,ID[X]+Tot[X],N,Z);
CloSeg(1,1,ID[X],Z);
return;
}
inline int Read(void){
int X=0,Y=1;char C=getchar();
while(C<'0'||C>'9'){if(C=='-'){Y=-1;}C=getchar();}
while('0'<=C&&C<='9'){X=X*10+(C-'0');C=getchar();}
return (X*Y);
}
struct Unsigned{
int From,To,Num;
friend bool operator <(Unsigned Num1,Unsigned Num2){
return Num1.Num>Num2.Num;
}
}Dis[MAXN];
int X,Y,Z;
int Xi[MAXN],Yi[MAXN],Zi[MAXN];
int main(void){
N=Read(),M=Read();
for(register int i=1;i<N;i++){
Xi[i]=Read(),Yi[i]=Read();
Add(Xi[i],Yi[i]);
Add(Yi[i],Xi[i]);
Zi[i]=Read();
}
DFS1(1,0);
for(register int i=1;i<N;i++){
if(Dep[Xi[i]]>=Dep[Yi[i]])
A[Xi[i]]=Zi[i];
else A[Yi[i]]=Zi[i];
}
DFS2(1,1);
Build(1,N,1);
for(register int i=1;i<=M;i++){
X=Read();Dis[i].From=X;
Y=Read();Dis[i].To=Y;
Dis[i].Num=SumTree(X,Y);
Clover(X,Y,Dis[i].Num);
}
int Min=1<<30;
sort(Dis+1,Dis+1+M);
int Z=Dis[1].Num;
for(register int i=1;i<=M;i++){
if(Z!=Dis[i].Num)
break;
X=Dis[i].From,Y=Dis[i].To;
while(Top[X]!=Top[Y]){
if(Dep[Top[X]]<Dep[Top[Y]])
swap(X,Y);
Min=min(Min,max(Z-A[X],MaxSeg(1,ID[X])));
X=Fa[X];
}
if(Dep[X]<Dep[Y])
swap(X,Y);
while(X!=Y){
Min=min(Min,max(Z-A[X],MaxSeg(1,ID[X])));
X=Fa[X];
}
}
cout<<Min<<endl;
return 0;
}
测评记录: