常规方法:最小生成树+LCA
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
int n, m, q, k, fa[MAXN], dep[MAXN], f[MAXN][22], lg[MAXN], maxn[MAXN][22];
bool c[MAXN];
struct node{
int u, l;
};
struct edge{
int u, v, l;
}e[300005];
bool cmp(edge x, edge y) {
return x.l < y.l;
}
vector<node> g[MAXN];
void init() {
for (int i = 1; i <= n; i++) fa[i] = i;
}
int find(int x) {
return fa[x] == x ? fa[x] : (fa[x] = find(fa[x]));
}
void dfs(int to, int fa) {
for(int i = 0; i < g[to].size(); i++) {
if(g[to][i].u != fa) {
dep[g[to][i].u] = dep[to] + 1;
f[g[to][i].u][0] = to;
maxn[g[to][i].u][0] = g[to][i].l;
dfs(g[to][i].u, to);
}
}
}
int lca(int x, int y) {
int ans = 0;
if(find(x) != find(y)) return -1;
if(dep[x] < dep[y]) swap(x, y);
while(dep[x] > dep[y]) {
ans = max(ans, maxn[x][lg[dep[x] - dep[y]] - 1]);
x = f[x][lg[dep[x] - dep[y]] - 1];
}
if(x == y) return ans;
for(int i = lg[dep[x]] - 1; i >= 0; i--) {
if(f[x][i] != f[y][i]) {
ans = max(ans, max(maxn[x][i], maxn[y][i]));
x = f[x][i], y = f[y][i];
}
}
ans = max(ans, max(maxn[x][0], maxn[y][0]));
return ans;
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].l);
init();
sort(e + 1, e + m + 1, cmp);
for(int i = 1; i <= m; i++) {
int x = find(e[i].u), y = find(e[i].v);
if(x != y) {
fa[x] = y;
g[e[i].u].push_back((node){e[i].v, e[i].l});
g[e[i].v].push_back((node){e[i].u, e[i].l});
//ru[e[i].]
k++;
if(k == n - 1) break;
}
}
for(int i = 1; i <= n; i++) lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
for(int i = 1; i <= n; i++) {
if(!c[fa[i]] && fa[i] != 1) {
dfs(fa[i], 0);
c[fa[i]] = true;
c[i] = true;
}
}
for(int i = 1; i <= 20; i++) {
for(int to = 1; to <= n; to++) {
f[to][i] = f[f[to][i - 1]][i - 1];
maxn[to][i] = max(maxn[to][i - 1], maxn[f[to][i - 1]][i - 1]);
}
}
scanf("%d", &q);
while(q--) {
int a, b;
scanf("%d%d", &a, &b);
if(find(a) != find(b)) puts("impossible\n");
else printf("%d\n", lca(a, b));
}
return 0;
}