booloperator<(const Edge &b) const { return w < b.w; } }; namespace KruskalTree { int fa[N]; int f[N][20]; int dep[N], a[N]; vector<int> g[N]; intfind(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } voidaddedge(int u, int v) { g[u].push_back(v); g[v].push_back(u); } voiddfs1(int x, int ff) { f[x][0] = ff; dep[x] = dep[ff] + 1; for (int i = 1; i <= 18; i++) f[x][i] = f[f[x][i - 1]][i - 1]; for (int to : g[x]) { if (to == ff) continue; dfs1(to, x); } } intlca(int u, int v) { if (dep[u] < dep[v]) swap(u, v); for (int i = 18; i >= 0; i--) { if (dep[f[u][i]] >= dep[v]) u = f[u][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]; } voidinit(int n, vector<Edge> e) { for (int i = 0; i <= n << 1; i++) fa[i] = i; int cnt = n; sort(e.begin(), e.end()); for (Edge now : e) { int u = now.u, v = now.v, w = now.w; int x = find(u), y = find(v); if (x == y) continue; cnt++; fa[x] = fa[y] = cnt; addedge(x, cnt); addedge(y, cnt); a[cnt] = w; }
for (int i = cnt; i >= 1; i--) if (!dep[i]) {
dfs1(i, 0); } }
} // namespace KruskalTree
intread() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar(); return x * f; }
usingnamespace KruskalTree; intmain() { int n = read(), m = read(); vector<Edge> e; for (int i = 1; i <= m; i++) { int u = read(), v = read(), w = read(); e.push_back((Edge){u, v, w}); } init(n, e); int q = read(); for (int i = 1; i <= q; i++) { int u = read(), v = read(); if (find(u) != find(v)) puts("impossible"); else printf("%d\n", a[lca(u, v)]); } }