SubTask1 10 个点情况:WA WA WA WA AC AC AC AC WA WA
SubTask2 10 个点情况:WA AC WA WA AC AC AC AC WA WA
//程序算法:LCA
#include <bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int tot,hd[N],to[N*2],ww[N*2],nxt[N*2];//邻接表
inline void add_edge(int u,int v,int w)
{
to[++tot]=v,ww[tot]=w,nxt[tot]=hd[u],hd[u]=tot;
}
//d[i]记录结点i的深度,dis[i]记录根到i的距离
//dist[i]记录第i格计划的路径长度。
int n,m,cnt[N],p[N],d[N],dis[N],dist[N],s[N],t[N],lca[N];
bool vis[N];
struct Query{
int id,y;//id为查询编号。
}q;
vector<Query> Q[N];
int find(int x)
{
if(x!=p[x])p[x]=find(p[x]);
return p[x];
}
//将x合并到y上。
void union_set(int x,int y)
{
x=find(x),y=find(y);
p[x]=y;
}
int maxdis,num,maxw;
int tarjan(int x)
{
p[x]=x;
for(int i=hd[x];i;i=nxt[i])
{
int v=to[i],w=ww[i];
if(!p[v])
{
dis[v]=dis[x]+w;
tarjan(v);
union_set(v,x);
}
}
vis[x]=true;
//枚举查询;
for(int i=0;i<Q[x].size();i++)
if(vis[Q[x][i].y])
{
int id=Q[x][i].id;
lca[id]=find(Q[x][i].y);
dist[id]=dis[s[id]]+dis[t[id]]-2*dis[lca[id]];
maxdis=max(maxdis,dist[id]);
}
}
int calc(int u,int fa)
{
for(int i=hd[u];i;i=nxt[i])
{
int v=to[i],w=ww[i];
if(v!=fa)
{
cnt[u]+=calc(v,u);
if(cnt[v]==num)maxw=max(maxw,w);
}
}
return cnt[u];
}
bool check(int mid)
{
num=0,maxw=0;
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=m;i++)
if(dist[i]>mid)
{
num++;
cnt[s[i]]++,cnt[t[i]]++,cnt[lca[i]]-=2;
}
if(!num)return true;//均小于等于m
calc(1,0);
return maxdis-maxw<=mid;
}
int main()
{
//freopen("input.in","r",stdin);
//freopen("output.out","w",stdout);
scanf("%d %d",&n,&m);
int u,v,w,l=0,r=1;
for(int i=1;i<n;i++)
{
scanf("%d %d %d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
r+=w;
}
//m个运输计划
for(int i=1;i<=m;i++)
{
scanf("%d %d",&s[i],&t[i]);
Q[s[i]].push_back(Query{i,t[i]});
Q[s[i]].push_back(Query{i,s[i]});
}
tarjan(1);
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
printf("%d\n",l);
return 0;
}