- 2015
T6
- @ 2025-10-6 16:34:52
#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 条评论
目前还没有评论...