因为有重边,所以我们将所有的边存起来,然后搞一个最小生成树,在生成的过程中记一下他们公共的节点,然后在查询的时候跑一个LCA算法,可以在
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的总体时间复杂度下的出答案
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = N << 1;
int h[N], e[M], ne[M], idx;
int fa[N][20], d[N], dist[N];
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u, int father) {
d[u] = d[father] + 1;
fa[u][0] = father;
for (int k = 1; k <= 18; k++)
fa[u][k] = fa[fa[u][k - 1]][k - 1];
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == father) continue;
dfs(j, u);
}
}
int lca(int x, int y) {
if (d[x] > d[y]) swap(x, y);
for (int i = 18; i >= 0; i--)
if (d[fa[y][i]] >= d[x])
y = fa[y][i];
if (x == y) return x;
for (int i = 18; i >= 0; i--)
if (fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
struct Edge {
int u, v, w;
} edges[M];
int f[N];
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++) cin >> edges[i].u >> edges[i].v >> edges[i].w;
sort(edges + 1, edges + m + 1, [&](const Edge A, const Edge B) {
return A.w < B.w;
});
for (int i = 1; i <= n * 2; i++) f[i] = i;
memset(h, -1, sizeof h);
int tot = n;
for (int i = 1; i <= m; i++) {
auto &[u, v, w] = edges[i];
u = find(u), v = find(v);
if (u == v) continue;
f[u] = f[v] = ++tot;
dist[tot] = w;
add(tot, u), add(tot, v);
}
dfs(tot, 0);
int q;
cin >> q;
while (q--) {
int l, r;
cin >> l >> r;
cout << dist[lca(l, r)] << "\n";
}
return 0;
}