Description
Input
Output
Hint
Solution
如果每次修改的不是最长边,那么修改将毫无意义。因此只会对某一路径上的最长边进行修改,且易得改动的边的变化长度dlen*经过次数t一定是最大的
考虑到有可能最长边len1-L<次长边len2,此时的最长边就变成了len2,减少的长度实际为len1-len2,那么树上倍增的同时记录最长边和次长边,把所有路径算出来即可找到答案
这倍增真尼玛难写
Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define max(x, y) ((x)>(y)?(x):(y))
#define min(x, y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<(0)?(-(x)):(x))
#define ll long long
#define N 100001
#define E N * 2 + 1
#define L 101
struct edge {int x, y, w, next;} e[E];
struct data {int x, y;} v[N];
int mx[N][21][2], fa[N][21], dep[N], cnt[N], ls[N];
int edgeCnt = 0;
ll INF;
inline int read() {
int x = 0; char ch = getchar();
for(; ch<'0'||ch>'9'; ch=getchar());
for(; ch<='9'&&ch>='0'; (x*=10)+=ch-'0',ch=getchar());
return x;
}
inline void addEdge(int x, int y, int w) {
e[++ edgeCnt] = (edge) {x, y, w, ls[x]}; ls[x] = edgeCnt;
e[++ edgeCnt] = (edge) {y, x, w, ls[y]}; ls[y] = edgeCnt;
}
inline void dfs(int now) {
rep(i, 1, 20) {
fa[now][i] = fa[fa[now][i - 1]][i - 1];
if (mx[now][i - 1][0] > mx[fa[now][i - 1]][i - 1][0]) {
mx[now][i][0] = mx[now][i - 1][0];
mx[now][i][1] = max(mx[now][i][1], mx[now][i - 1][1]);
mx[now][i][1] = max(mx[now][i][1], mx[fa[now][i - 1]][i - 1][0]);
}else {
mx[now][i][0] = mx[fa[now][i - 1]][i - 1][0];
mx[now][i][1] = max(mx[now][i][1], mx[now][i - 1][0]);
mx[now][i][1] = max(mx[now][i][1], mx[fa[now][i - 1]][i - 1][1]);
}
}
erg(i, now) {
if (e[i].y == fa[now][0]) {continue;}
dep[e[i].y] = dep[now] + 1;
mx[e[i].y][0][0] = e[i].w;
mx[e[i].y][0][1] = -INF;
fa[e[i].y][0] = now;
dfs(e[i].y);
}
}
inline data lca(int x, int y) {
int tx1 = 0;
int tx2 = 0;
int ty1 = 0;
int ty2 = 0;
if (dep[x] <= dep[y]) {
x ^= y;
y ^= x;
x ^= y;
}
drp(i, 20, 0) {
if (dep[fa[x][i]] >= dep[y]) {
if (mx[x][i][0] > tx1) {
tx2 = max(tx1, mx[x][i][1]);
tx1 = mx[x][i][0];
}else if (mx[x][i][0] > tx2) {
tx2 = mx[x][i][0];
}else if (mx[x][i][1] > tx2) {
tx2 = mx[x][i][1];
}
x = fa[x][i];
}
}
if (x == y) {
return (data) {tx1, tx2};
}
drp(i, 20, 0) {
if (fa[x][i] != fa[y][i]) {
if (mx[x][i][0] > tx1) {
tx2 = max(tx1, mx[x][i][1]);
tx1 = mx[x][i][0];
}else if (mx[x][i][0] > tx2) {
tx2 = mx[x][i][0];
}else if (mx[x][i][1] > tx2) {
tx2 = mx[x][i][1];
}
x = fa[x][i];
if (mx[y][i][0] > ty1) {
ty2 = max(ty1, mx[y][i][1]);
ty1 = mx[y][i][0];
}else if (mx[y][i][0] > ty2) {
ty2 = mx[y][i][0];
}else if (mx[y][i][1] > ty2) {
ty2 = mx[y][i][1];
}
y = fa[y][i];
}
}
int i = 0;
if (mx[x][i][0] > tx1) {
tx2 = max(tx1, mx[x][i][1]);
tx1 = mx[x][i][0];
}else if (mx[x][i][0] > tx2) {
tx2 = mx[x][i][0];
}else if (mx[x][i][1] > tx2) {
tx2 = mx[x][i][1];
}
x = fa[x][i];
if (mx[y][i][0] > ty1) {
ty2 = max(ty1, mx[y][i][1]);
ty1 = mx[y][i][0];
}else if (mx[y][i][0] > ty2) {
ty2 = mx[y][i][0];
}else if (mx[y][i][1] > ty2) {
ty2 = mx[y][i][1];
}
y = fa[y][i];
if (ty1 > tx1) {
tx2 = max(tx1, ty2);
tx1 = ty1;
}else {
tx2 = max(tx2, ty1);
}
return (data) {tx1, tx2};
}
inline bool cmp(data a, data b){
return a.x > b.x;
}
int main(void) {
INF = 1;
rep(i, 1, 62) {
INF = INF * 2;
}
INF = INF - 1;
INF = INF + INF + 1;
int n = read();
int m = read();
int l = read();
rep(i, 2, n) {
int x = read();
int y = read();
int w = read();
addEdge(x, y, w);
}
dep[1] = 1;
dfs(1);
ll tot = 0;
rep(i, 1, m) {
int x = read();
int y = read();
v[i] = lca(x, y);
tot += v[i].x;
}
std:: sort(v + 1, v + n + 1, cmp);
ll ans = INF;
rep(i, 1, n - 1) {
int j = i;
ll tmp = tot;
tmp -= l;
if (v[j].x - l < v[j].y) {
tmp = tmp + l - v[j].x + v[j].y;
}
ans = min(ans, tmp);
while (j < n && v[j].x == v[j + 1].x) {
j += 1;
tmp -= l;
if (v[j].x - l < v[j].y) {
tmp = tmp + l - v[j].x + v[j].y;
}
ans = min(ans, tmp);
}
i = j;
}
std:: cout << ans << std:: endl;
return 0;
}