树上有许多条路径,现在你可以将一条边的权值设为0,令所有路径的最大值最小。
我们注意到,设为0的边如果不在最长路径上,就不会减小答案。
因此我们可以找出最长路径,把原树转化为一条链+许多树的模型。
预处理出每个点i的from[i]表示由链上哪个点延伸的。
接下来我们可以枚举将链上哪条边变为0,则经过这条边的最长路径一定是最长链,我们只需维护出不经过这条边的最长路径。这个显然可以转化为添加删除问题,用set维护(n log n此题可能T,还有o(n)的方法也很简单,读者自行思考)。
lca应有tarjan打避免t的危险。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<set>
#include<algorithm>
#include<iostream>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=300000+10;
struct dong{
int x;
friend bool operator <(dong a,dong b){
return a.x>b.x;
}
};
multiset<dong> t2;
int f[maxn][20],g[maxn],h[maxn],go[maxn*2],next[maxn*2],dis[maxn*2],u[maxn],v[maxn],w[maxn],fa[maxn];
int sum[maxn],num[maxn],a[maxn],d[maxn],dfn[maxn],nfd[maxn],fi[maxn],bh[maxn],zou[maxn],xia[maxn],from[maxn],dl[maxn];
int i,j,k,l,s,t,n,m,tot,ans,xdl;
bool bz[maxn];
dong suan;
int read(){
int x=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
void add(int x,int y,int z){
go[++tot]=y;
dis[tot]=z;
next[tot]=h[x];
h[x]=tot;
}
void add2(int x,int y,int z){
zou[++tot]=y;
bh[tot]=z;
xia[tot]=fi[x];
fi[x]=tot;
}
int getfa(int x){
return fa[x]?fa[x]=getfa(fa[x]):x;
}
void dfs(int x,int y){
d[x]=d[y]+1;
f[x][0]=y;
int t=h[x];
while (t){
if (go[t]!=y){
g[go[t]]=dis[t];
sum[go[t]]=sum[x]+dis[t];
dfs(go[t],x);
}
t=next[t];
}
}
void color(int x,int y){
from[x]=y;
int t=h[x];
while (t){
if (!from[go[t]]&&d[go[t]]==d[x]+1) color(go[t],y);
t=next[t];
}
}
void up(int x){
if (!x) return;
color(x,x);
up(f[x][0]);
}
void tarjan(int x,int y){
bz[x]=1;
int t=h[x];
while (t){
if (go[t]!=y){
tarjan(go[t],x);
fa[go[t]]=x;
}
t=next[t];
}
t=fi[x];
while (t){
if (bz[zou[t]]){
w[bh[t]]=getfa(zou[t]);
}
t=xia[t];
}
}
void solve(int x){
if (!x) return;
int t=fi[x];
while (t){
if (!bh[t]){
suan.x=a[zou[t]];
t2.erase(suan);
}
t=xia[t];
}
t=fi[x];
while (t){
if (bh[t]){
suan.x=a[zou[t]];
t2.insert(suan);
}
t=xia[t];
}
//if (x==5) printf("%d\n",(*(t2.begin())).x);
ans=min(ans,max(xdl-g[x],(*(t2.begin())).x));
solve(f[x][0]);
}
int main(){
freopen("transport.in","r",stdin);freopen("transport.out","w",stdout);
n=read();m=read();
fo(i,1,n-1){
j=read();k=read();t=read();
add(j,k,t);add(k,j,t);
}
tot=0;
dfs(1,0);
tot=0;
fo(i,1,m){
u[i]=read();v[i]=read();
add2(u[i],v[i],i);
add2(v[i],u[i],i);
}
tarjan(1,0);
xdl=0;
fo(i,1,m){
a[i]=sum[u[i]]+sum[v[i]]-sum[w[i]]*2;
if (a[i]>xdl){
xdl=a[i];
s=u[i];
t=v[i];
}
}
d[0]=0;
dfs(s,0);
up(t);
tot=0;
fill(fi+1,fi+n+1,0);
fo(i,1,m){
j=u[i];k=v[i];
if (d[from[j]]>d[from[k]]) swap(j,k);
add2(from[k],i,0);add2(from[j],i,1);
}
ans=1000000000;
fo(i,1,m){
suan.x=a[i];
t2.insert(suan);
}
solve(t);
printf("%d\n",ans);
fclose(stdin);fclose(stdout);
return 0;
}