#include<bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;

const int N = 300010, M = N * 2;

int n, m;
int h[N], e[M], w[M], ne[M], idx;
int dist[N], depth[N];
int f[N][20], seq[N], cnt;
int sum[N];
PII trans[N];
int blca[N];

void add(int a, int b, int c)
{
    e[idx] = b;
    w[idx] = c;
    ne[idx]= h[a];
    h[a] = idx ++;
}

void dfs(int u, int dep, int fa)
{
    cnt ++;
    seq[cnt] = u;
    depth[u] = dep;
    for(int i = 1; i < 20; i++) f[u][i] = f[f[u][i - 1]][i - 1];

    for(int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];
        if(j != fa)
        {
            dist[j] = dist[u] + w[i];
            f[j][0] = u;
            dfs(j, dep  + 1, u);
        }
    }
}

int lca(int x, int y)
{
    if(depth[x] < depth[y]) swap(x, y);
    int d = depth[x] - depth[y];
    for(int i = 0; i < 20; i++)
        if(d >> i & 1)
            x = f[x][i];
    
    if(x == y) return x;

    for(int i = 19; i >= 0; i--)
        if(f[x][i] != f[y][i])
        {
            x = f[x][i], y = f[y][i];
        }
    
    return f[x][0];
}


bool check(int mid)
{
    memset(sum, 0, sizeof sum);
    int maxd = 0, s = 0;
    for(int i = 1; i <= m; i++)
    {
        int x = trans[i].first, y = trans[i].second;
        int p = blca[i];
        int d = dist[x] + dist[y] - dist[p] * 2;
        if(d > mid)
        {
            sum[x] += 1, sum[y] += 1;
            sum[p] -= 2;
            maxd = max(maxd, d - mid);
            s ++;
        }
    }

    if(!s) return true;

    for(int i = n; i; i--)
    {
        int x = seq[i];
        sum[f[x][0]] += sum[x];
    }

    for(int i = 1; i <= n; i++)
        if(sum[i] == s && dist[i] - dist[f[i][0]] >= maxd)
            return true;
    
    return false;
}

int main()
{
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof h);
    for(int i = 0; i < n - 1; i++)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c), add(b, a,  c);
    }
    dfs(1, 0, -1);

    for(int i = 1; i <= m; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        trans[i] = {x, y};
        blca[i] = lca(x, y);
    }

    int l = 0, r = 1e9;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(check(mid)) r = mid;
        else l = mid + 1;
    }
    printf("%d\n", r);
    return 0;
}
/*
二分时间:将问题转化成一个判定性问题,判断是否可以将一条边权变为0,使得所有路径的长度<=mid

(1)先求出每个路径的长度  O(nlogn)
    可以用lca和前缀和来计算
    假设a和b的公共祖先是p
    设dist[a] 表示点a到根节点的路径长度。
    则a到b的路径长度 = dist[a] + dist[b] - 2*dist[p]
(2)将路径分为两类d(a, b) <= mid 和 d(a, b) > mid
    对于第一类显然是符合条件的,无需处理
    对于第二类我们可以让其中一条公共边变为0
    预处理第二类路径上的所有边O(n)
    用树上差分
(3)枚举每一条公共边,判断这条边的权值清除后,是否满足mid
总时间复杂度为:O((n + m)logT) T为路径长度的最大值
O(MlogN) + O((n + m)logT)
*/

0 条评论

目前还没有评论...