cin >> n >> k >> q;
for (int i = 1; i <= n - 1; i++) {
int x, y;
cin >> x >> y;
e[x].push_back(y);
e[y].push_back(x);
}
for (int i = 1; i <= k; i++)
cin >> door[i];
void dfs(int fa, int x) {
dist[x] = dist[fa] + 1;
f[x][0] = fa; // x的第2^0(1)个祖先就是它爹
for (int i = 1; i <= 18; i++)
f[x][i] = f[f[x][i - 1]][i - 1]; // x的第2^i个祖先就是 它2^(i-1)个祖先的第2^(i-1)个祖先 因为2^i = 2^(i-1) + 2^(i-1)
for (int u : e[x]) {
if (u != fa)
dfs(x, u);
}
}
LCA中也要改动。
cpp复制代码
int lca(int u, int v) {
// 1
if (dist[u] > dist[v])
swap(u, v);
for (int i = 18; i >= 0; i--) { // 2^18 > 2*10^5
if (dist[u] <= dist[f[v][i]])
v = f[v][i];
if (u == v) return u;
}
//2
for (int i = 18; i >= 0; i--) {
if (f[u][i] != f[v][i])
u = f[u][i], v = f[v][i];
}
return f[u][0]; // u和v最后是它们公共祖先的两个儿子 所以它们公共祖先是它们任意一个的父亲
}
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 200005;
vector<int> e[N];
int n, k, q, door[N]; // door[] 存放每个传送点
int dist[N] = {-1}, f[N][20]; // dist[] 每个点离根节点的距离 f[x][i] 节点 x 的 第2^i 个祖先(从下往上)
int dst[N]; // dst[i] = i 到 离i最近的传送点 的距离
void bfs() {
memset(dst, 0x3f, sizeof (dst));
queue<int> qu;
for (int i = 1; i <= k; i++) {
qu.push(door[i]); // 存入所有的传送点
dst[door[i]] = 0;
}
while (!qu.empty()) {
int now = qu.front();
qu.pop();
for (int x : e[now]) {
if (dst[x] == 0x3f3f3f3f) {
dst[x] = dst[now] + 1; // 更新x离最近传送点的位置
qu.push(x);
}
}
}
}
void dfs(int fa, int x) {
dist[x] = dist[fa] + 1;
f[x][0] = fa;
for (int i = 1; i <= 18; i++)
f[x][i] = f[f[x][i - 1]][i - 1];
for (int u : e[x]) {
if (u != fa)
dfs(x, u);
}
}
int lca(int u, int v) {
if (dist[u] > dist[v])
swap(u, v);
for (int i = 18; i >= 0; i--) {
if (dist[u] <= dist[f[v][i]])
v = f[v][i];
if (u == v) return u;
}
for (int i = 18; i >= 0; i--) {
if (f[u][i] != f[v][i])
u = f[u][i], v = f[v][i];
}
return f[u][0];
}
int solve(int u, int v) {
// ** 使用传送门
int res1 = dst[u] + dst[v]; // 找离起点最近的传送点 传送至 离终点最近的传送点
// **不使用传送门
int res2 = dist[u] + dist[v] - 2 * dist[lca(u, v)];
return min(res1, res2); // 取小者
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> k >> q;
for (int i = 1; i <= n - 1; i++) {
int x, y;
cin >> x >> y;
e[x].push_back(y);
e[y].push_back(x);
}
for (int i = 1; i <= k; i++)
cin >> door[i];
bfs();
dfs(0, 1);
while (q--) {
int u, v;
cin >> u >> v;
cout << solve(u, v) << endl;
}
return 0;
}