版权声明:Fashion Education https://blog.csdn.net/ModestCoder_/article/details/88980770
@LuoGu
本题两个询问,dist询问是lca基本做法吧
主要是kth询问
其实也是lca,跟树剖一点关系也没有~
先求一遍lca,可以知道kth的点在s->lca(s,t)上还是lca(s,t)->t上
之后再倍增跑一边即可~
Code:
#include <bits/stdc++.h>
#define maxn 10010
using namespace std;
struct Edge{
int to, len, next;
}edge[maxn << 1];
int head[maxn << 1], fa[maxn][30], d[maxn], dis[maxn], num, n;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void add_edge(int x, int y, int z){ edge[++num].to = y; edge[num].len = z; edge[num].next = head[x]; head[x] = num; }
void build(int u){
for (int i = 0; fa[u][i]; ++i) fa[u][i + 1] = fa[fa[u][i]][i];
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (v != fa[u][0]){
d[v] = d[u] + 1, dis[v] = dis[u] + edge[i].len, fa[v][0] = u;
build(v);
}
}
}
int lca(int u, int v){
if (d[u] < d[v]) swap(u, v);
for (int i = 20; i >= 0; --i) if (d[v] + (1 << i) <= d[u]) u = fa[u][i];
if (u == v) return u;
for (int i = 20; i >= 0; --i) if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
return fa[u][0];
}
int query(int u, int v, int k){
int x = lca(u, v);
if (k <= d[u] - d[x] + 1){
--k;
for (int i = 20; i >= 0; --i) if (k >= (1 << i)) k -= (1 << i), u = fa[u][i];
return u;
} else{
k = d[u] + d[v] - (d[x] << 1) + 1 - k;
for (int i = 20; i >= 0; --i) if (k >= (1 << i)) k -= (1 << i), v = fa[v][i];
return v;
}
}
int main(){
int M = read();
while (M--){
num = 0;
memset(head, 0, sizeof(head));
memset(edge, 0, sizeof(edge));
memset(d, 0, sizeof(d));
memset(dis, 0, sizeof(dis));
memset(fa, 0, sizeof(fa));
n = read();
for (int i = 1; i < n; ++i){
int x = read(), y = read(), z = read();
add_edge(x, y, z); add_edge(y, x, z);
}
build(1);
while (1){
char c = getchar();
for (; c != 'I' && c != 'T' && c != 'O'; c = getchar());
if (c == 'O') break;
if (c == 'I'){
int x = read(), y = read();
printf("%d\n", dis[x] + dis[y] - (dis[lca(x, y)] << 1));
} else{
int x = read(), y = read(), z = read();
printf("%d\n", query(x, y, z));
}
}
}
return 0;
}