
一道倍增 LCA 的裸题。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <bits/stdc++.h>
using namespace std;
const int ESIZ = 1E5;
typedef pair<int, int> PII;
struct tgno {
int u, v, w;
tgno *n;
} POOL[ESIZ]; int ppos;
tgno* Head[ESIZ];
void _add(int u, int v, int w) {
POOL[ppos].u = u; POOL[ppos].v = v;
POOL[ppos].w = w; POOL[ppos].n = Head[u];
Head[u] = &POOL[ppos++];
}
void addEdge(int u, int v, int w) {
_add(u, v, w); _add(v, u, w);
}
int N, M;
int vis[ESIZ];
int dep[ESIZ], pre[ESIZ][20], dis[ESIZ][20];
void dfs(int curr) {
typedef tgno* It;
for(It i=Head[curr];i;i=i->n) {
if(!dep[i->v]) {
dep[i->v] = dep[curr] + 1;
pre[i->v][0] = curr;
dis[i->v][0] = i->w;
dfs(i->v);
}
}
}
void mkLCA(int R) {
memset(vis, 0x00, sizeof(vis));
memset(dep, 0x00, sizeof(dep));
memset(dis, 0x3F, sizeof(dis)); dep[R]=1;
dfs(R);
for(int j=1;(1<<j)<=N;j++) {
for(int i=1;i<=N;i++) {
if(pre[i][j-1]) {
pre[i][j] = pre[pre[i][j-1]][j-1];
dis[i][j] = dis[i][j-1] + dis[pre[i][j-1]][j-1];
}
}
}
}
// < LCA, Distance >
PII LCA(int A, int B) {
int dd = 0, i, j, a = A, b = B;
if(dep[a] < dep[b]) swap(a, b);
for(i=0;(1<<i)<=dep[a];i++);
i--;
for(j=i;j>=0;j--)
if(dep[a]-(1<<j)>=dep[b]) {
dd += dis[a][j]; a = pre[a][j];
}
if(a == b) return PII(a, dd);
for(j=i;j>=0;j--) {
if(pre[a][j] && pre[a][j] != pre[b][j]) {
dd += dis[a][j]; a = pre[a][j];
dd += dis[b][j]; b = pre[b][j];
}
}
return PII(pre[a][0], dd + dis[a][0] + dis[b][0]);
}
int main() {
int T; cin >> T;
while(T--) {
memset(POOL, 0x00, sizeof(POOL));
memset(Head, 0x00, sizeof(Head));
cin >> N >> M;
int u, v, w; int _ = N-1;
for(int i=0;i<_;i++) {
cin >> u >> v >> w; addEdge(u, v, w);
}
mkLCA(1);
for(int i=0;i<M;i++) {
cin >> u >> v;
cout << LCA(u, v).second << endl;
}
}
}




近期评论