最长的路径最短,可以考虑二分ans。验证ans成不成立。
如果能找到一条边,删去这边后,所有大于ans的路径都小于ans 了,那么成了。
这条边一定要被所有大于ans的路径经过,并且是所有满足这个条件的边的边权最大的那条。
计算树上一条边被经过次数差分啊! 起点+1,终点+1,lca-2.(lca可以用倍增,tarjian,树剖,个人喜好吧)。
对于一个点,以它为根的子树的权值和(权值和包括它自己啊)就是它到它父亲这条边被经过的次数。
把满足被所有大于ans的路径经过边权最大的边找到。枚举每个大于ans的路径。如果有一条路径长度-这条边的边权 > ans,
说明ans不成立。
优化:
1.二分的左边界,最长的路径-最大边权。右边界为最长的路径。
2.提前预处理出每个运输计划起点和终点的lca.
//在算大于ans的路径数时,cnt一定要清0啊,我就是这个没清,吓的我以为我边都建错了。。。。调了好久。。。。改清的一定要清干净啊!
复杂度应该是log最大边权 m的。
#include<bits/stdc++.h>
using namespace std;
const int N = 300005;
int n,m, ma, dis[N], dis1[N], cha[N], zong[N], cnt, k, maa, ql[N], qr[N], lc[N];
int dep[N], top[N], son[N], siz[N],fa[N];
int tp, nex[2*N], tov[2*N], tow[2*N], h[N];
void read(int &x)
{
x = 0; int f = 0 ; char c = getchar();
while(c < '0' || c > '9')
{
if(c == '-') f = 1; c = getchar();
}
while(c >= '0' && c <= '9')
{
x = x * 10 + c - '0'; c = getchar();
}
if(f) x = -x;
}
void add(int x,int y,int w)
{
tp++;
tov[tp] = y; tow[tp] = w; nex[tp] = h[x]; h[x] = tp;
}
void dfs(int x,int u)
{
fa[x] = u; siz[x] = 1;
for(int i = h[x]; i; i = nex[i])
{
int v = tov[i];
if(v == fa[x]) continue;
dep[v] = dep[x] + 1;
dfs(v,x);
siz[x] += siz[v];
if(siz[v] > siz[son[x]]) son[x] = v;
}
}
void dfs1(int x,int u)
{
top[x] = u;
if(son[x]) dfs1(son[x],u);
for(int i = h[x]; i; i = nex[i])
{
int v = tov[i];
if(v == son[x] || v == fa[x]) continue;
dfs1(v,v);
}
}
int lca(int x,int u,int i)
{
while(top[x] != top[u])
{
if(dep[top[x]] > dep[top[u]]) swap(x,u); u = fa[top[u]];
}
return dep[x] > dep[u] ? u : x;
}
void dfs2(int x)
{
zong[x] = cha[x];
for(int i = h[x]; i; i = nex[i])
{
int v = tov[i];
if(v == fa[x]) continue;
dfs2(v);
zong[x] += zong[v];
if(zong[v] == cnt){k = max(k,tow[i]);}
}
}
void dfs3(int x)
{
for(int i = h[x]; i; i = nex[i])
{
int v = tov[i];
if(v == fa[x]) continue;
dis1[v] = dis1[x] + tow[i];
dfs3(v);
}
}
int check(int x)
{
memset(zong,0,sizeof(zong));
memset(cha,0,sizeof(cha)); k = 0;cnt = 0;
for(int i = 1; i <= m; i++)
if(dis[i] > x)
{
cnt++; cha[ql[i]] ++; cha[qr[i]] ++ ; cha[lc[i]] -= 2;
}
dfs2(1);
for(int i = 1; i <= m; i++)
if(dis[i] - k > x) return 0;
return 1;
}
int main()
{
read(n);read(m);
for(int i = 1; i < n; i++)
{
int x,y,w;
read(x);read(y);read(w); ma = max(w,ma);
add(x,y,w);add(y,x,w);
}
dfs(1,0); dfs1(1,0); dfs3(1);
for(int i = 1; i <= m; i++)
{
read(ql[i]);read(qr[i]);
lc[i] = lca(ql[i],qr[i],i);
dis[i] = dis1[ql[i]] + dis1[qr[i]] - 2 * dis1[lc[i]];
maa = max(maa, dis[i]);
}
int l = maa - ma , r = maa , ans = 0;
while(l <= r)
{
int mid = (l + r) / 2;
if(check(mid))
{ans = mid; r = mid - 1;}
else l = mid + 1;
}
printf("%d",ans);
return 0;
}