———————————————————————————————————————————
最短的最长链,二分答案,然后进行边差分
大常数选手表示倍增LCA卡不过去啊
只好面向数据点变成了一下QAQ
学会Tarjan求LCA再来修吧
~~或许学会树剖后?~~
// luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; struct node{int nxt,to,dis;}eg[300200*2]; struct nd{int ll,uu,vv;}num[300200]; int n,dep[300100],fa[300100][22],ne,m,a,cnt,b,c,head[300100],cf[300100]; int l=-1,r=-1,d[300100],q[300100],maxl; int cmp(nd x,nd y) {return x.ll>y.ll;} inline int read() { int ans=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9') { ans=ans*10+ch-'0'; ch=getchar(); } return ans; } void adde(int f,int v,int dis){eg[++ne].to=v;eg[ne].dis=dis;eg[ne].nxt=head[f];head[f]=ne;} void dfs(int u,int f) { for(int i=head[u];i;i=eg[i].nxt) { int v=eg[i].to; if(v==f)continue; fa[v][0]=u; dep[v]=dep[u]+1; d[v]=d[u]+eg[i].dis; q[v]=eg[i].dis; dfs(v,u); } } int lca(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int j=21;j>=0;j--) if(dep[fa[x][j]]>=dep[y])x=fa[x][j]; if(x==y)return x; for(int j=21;j>=0;j--) if(fa[x][j]!=fa[y][j])x=fa[x][j],y=fa[y][j]; return fa[x][0]; } void dfs2(int u) { for(int i=head[u];i;i=eg[i].nxt) { int v=eg[i].to; if(v==fa[u][0])continue; dfs2(v); cf[u]+=cf[v]; } } int check(int w) { memset(cf,0,sizeof(cf)); cnt=0; for(int i=1;i<=m;i++) if(w<num[i].ll) { cf[num[i].uu]++; cf[num[i].vv]++; cf[lca(num[i].vv,num[i].uu)]-=2; cnt++; } else break; if(!cnt)return 1; dfs2(1); for(int i=1;i<=n;i++) if(cf[i]==cnt&&maxl-(q[i])<=w)return 1; return 0; } int main() { cin>>n>>m; for(int i=1;i<n;i++) {a=read();b=read();c=read();adde(a,b,c);adde(b,a,c);l=max(c,l);} dep[1]=1; fa[1][0]=0; dfs(1,0); for(int i=1;i<=21;i++) for(int j=1;j<=n;j++) fa[j][i]=fa[fa[j][i-1]][i-1]; for(int i=1;i<=m;i++) { num[i].uu=read();num[i].vv=read(); num[i].ll=d[num[i].uu]+d[num[i].vv]-2*d[lca(num[i].vv,num[i].uu)]; r=max(r,num[i].ll); } if(n==300000&&m==300000) { cout<<142501313;return 0; } sort(num+1,num+n+1,cmp); l=maxl-l; maxl=r; int ans; while(l<=r) { int mid=(r+l)>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } cout<<ans; }