二分+树上差分
T了一个点
就5分不想了
二分一个最大长度
超过这个长度的路线
找它们的交
Tarjan找LCA
u,v+1
LCA-2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<climits>
#include<cstdlib>
#include<ctime>
#include<cstring>
#include<queue>
#define LL long long
using namespace std;
int cnt1,cnt2,v1[300005],v2[300005],num1[300005],num2[300005],nxt1[300005],nxt2[300005],head1[300005],head2[300005];
int c[300005],ques[300005],fa[300005],dt[300005],dep[300005],dis[300005],n,m,u[300005],v[300005],f[300005];
bool vis[300005];
void add1(int p1,int p2,int val)
{
cnt1++;
v1[cnt1]=val;
num1[cnt1]=p2;
nxt1[cnt1]=head1[p1];
head1[p1]=cnt1;
}
void add2(int p1,int p2,int val)
{
cnt2++;
v2[cnt2]=val;
num2[cnt2]=p2;
nxt2[cnt2]=head2[p1];
head2[p1]=cnt2;
}
int find(int x)
{
if(f[x]==x) return x;
f[x]=find(f[x]);
return f[x];
}
void tarjan(int x)
{
int i;
vis[x]=1;
for(i=head1[x];i;i=nxt1[i])
if(!vis[num1[i]])
{
tarjan(num1[i]);
f[num1[i]]=x;
}
for(i=head2[x];i;i=nxt2[i])
if(vis[num2[i]])
ques[v2[i]]=find(num2[i]);
}
void DFS(int x,int pre)
{
int i;
for(i=head1[x];i;i=nxt1[i])
if(num1[i]!=pre)
{
DFS(num1[i],x);
c[x]+=c[num1[i]];
fa[num1[i]]=v1[i];
}
}
bool check(int x)
{
int i,maxn=0,tot=0,maxdis;
memset(c,0,sizeof(c));
for(i=1;i<=m;i++)
if(dt[i]>x)
{
c[u[i]]++;
c[v[i]]++;
c[ques[i]]-=2;
tot++;
maxn=max(maxn,dt[i]);
}
DFS(1,0);
maxdis=maxn;
for(i=1;i<=n;i++)
if(c[i]==tot)
maxdis=min(maxdis,maxn-fa[i]);
if(maxdis>x) return 0;
return 1;
}
void dfs(int x,int pre)
{
int i;
dep[x]=dep[pre]+1;
for(i=head1[x];i;i=nxt1[i])
if(num1[i]!=pre)
{
dis[num1[i]]=dis[x]+v1[i];
dfs(num1[i],x);
}
}
int main()
{
int i,l=0,r=0,mid,a,b,t,ans;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
f[i]=i;
for(i=1;i<n;i++)
{
scanf("%d%d%d",&a,&b,&t);
add1(a,b,t);
add1(b,a,t);
r+=t;
}
dfs(1,0);
for(i=1;i<=m;i++)
{
scanf("%d%d",&u[i],&v[i]);
add2(u[i],v[i],i);
add2(v[i],u[i],i);
}
tarjan(1);
for(i=1;i<=m;i++)
dt[i]=dis[u[i]]+dis[v[i]]-2*dis[ques[i]];
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
printf("%d",ans);
return 0;
}