考虑二分
把所有超过mid的链取交集,然后取交集上最长的边权赋0,判断
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define V G[p].v
using namespace std;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
struct Seg_SUM{
int M,TH;
int T[400005],H[400005];
inline void Build (int n)
{
for (M=1,TH=0;M<n+2;M<<=1,TH++);
}
inline void Add(int s,int t,int c)
{
for (s+=M-1,t+=M+1;s^t^1;s>>=1,t>>=1)
{
if (~s&1) T[s^1]+=c;
if ( t&1) T[t^1]+=c;
}
}
inline int Query(int s)
{
int ret=0;
ret+=T[s+=M];
while (s>>=1)
ret+=T[s];
return ret;
}
}Seg;
const int N=300005;
struct edge{
int u,v,w,next;
};
edge G[2*N];
int head[N],inum;
inline void add(int u,int v,int w,int p){
G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p;
}
int size[N],depth[N],fat[N],dis[N];
int clk,tid[N],top[N];
void dfs(int u,int fa){
fat[u]=fa; depth[u]=depth[fa]+1; size[u]=1;
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
{
dis[V]=dis[u]+G[p].w;
dfs(V,u),size[u]+=size[V];
}
}
void find(int u,int fa,int z){
tid[u]=++clk; top[u]=z;
int maximum=0,son=0;
for (int p=head[u];p;p=G[p].next)
if (V!=fa && size[V]>maximum)
maximum=size[son=V];
if (son) find(son,u,z);
for (int p=head[u];p;p=G[p].next)
if (V!=fa && V!=son)
find(V,u,V);
}
inline int LCA(int u,int v){
for (;top[u]!=top[v];u=fat[top[u]])
if (depth[top[u]]<depth[top[v]])
swap(u,v);
if (depth[u]>depth[v]) swap(u,v);
return u;
}
int n,m;
struct event{
int u,v,lca,dis;
}eve[N];
inline void Modify(int u,int v,int r){
for (;top[u]!=top[v];u=fat[top[u]])
{
if (depth[top[u]]<depth[top[v]]) swap(u,v);
Seg.Add(tid[top[u]],tid[u],r);
}
if (depth[u]>depth[v]) swap(u,v);
Seg.Add(tid[u],tid[v],r);
}
inline bool Check(int mid){
int maxd=0,cnt=0;
for (int i=1;i<=m;i++)
if (eve[i].dis>mid)
{
++cnt;
Modify(eve[i].u,eve[i].v,1);
maxd=max(maxd,eve[i].dis);
}
int maxl=0;
for (int i=1;i<=n;i++)
if (i!=1 && Seg.Query(tid[i])==cnt && Seg.Query(tid[fat[i]])==cnt)
maxl=max(maxl,dis[i]-dis[fat[i]]);
for (int i=1;i<=m;i++)
if (eve[i].dis>mid)
Modify(eve[i].u,eve[i].v,-1);
return maxd-maxl<=mid;
}
int maxd=0;
inline void Bin()
{
Seg.Build(n);
int L=0,R=maxd,MID;
while (L+1<R)
if (Check(MID=(L+R)>>1))
R=MID;
else
L=MID;
printf("%d\n",R);
}
int main()
{
int iu,iv,iw;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
for (int i=1;i<n;i++)
read(iu),read(iv),read(iw),add(iu,iv,iw,++inum),add(iv,iu,iw,++inum);
dfs(1,0); find(1,0,1);
for (int i=1;i<=m;i++)
{
read(iu),read(iv);
eve[i].u=iu; eve[i].v=iv;
eve[i].lca=LCA(iu,iv); eve[i].dis=dis[iu]+dis[iv]-2*dis[eve[i].lca];
maxd=max(maxd,eve[i].dis);
}
Bin();
return 0;
}