#include<iostream> #include<cstdio> #include<algorithm> #include<ctype.h> #include<cstring> usingnamespace std; constint maxn = 50010; inlineintread() { int x = 0, w = 1; char c = getchar(); while (!isdigit(c)) { if (c == '-') w = -1; c = getchar(); } while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); return x * w; } int n, m, t; int fa[maxn], e[maxn], rank[maxn]; structdata { // 这是边 int x, y, z; } a[maxn];
inlineboolcmp(data a, data b){ return a.z < b.z; } inlineintfind(int x){ return fa[x] == x ? x : find(fa[x]); } inlinevoidkruskal() { int s = 0, f1, f2; for (int i = 1; i <= n; i++) fa[i] = i, rank[i] = 1; for (int i = 1; i <= m; i++) { f1 = find(a[i].x); f2 = find(a[i].y); if (f1 != f2) { if (rank[f1] < rank[f2]) { fa[f1] = f2; e[f1] = a[i].z; rank[f2] = max(rank[f2], rank[f1] + 1); } // 高度大的做小的的根 else { fa[f2] = f1; e[f2] = a[i].z; rank[f1] = max(rank[f1], rank[f2] + 1); } // 相等或者相反就相反来 s++; } if (s == n - 1) break; } } int c[maxn]; intquery(int x, int y) { for (int i = 1; i <= n; i++) c[i] = -1; int tmp = 0, ans = 0; while (1) { c[x] = tmp; // c是从x开始向上边的最大值。 if (fa[x] == x) break; tmp = max(tmp, e[x]); // e代表向上连接的边权 x = fa[x]; // 向上爬 } while (1) { if (c[y] >= 0) { ans = max(ans, c[y]); break; } // 找到LCA就break if (fa[y] == y) break; // 或者找到根 ans = max(ans, e[y]); y = fa[y]; } // 因为一定会集中到LCA就直接用ans return ans; } intmain() { while (~scanf("%d%d", &n, &m)) { for (int i = 1; i <= m; i++) { a[i] = (data){read(), read(), read()}; } sort(a + 1, a + 1 + m, cmp); kruskal(); t = read(); for (int x, y, i = 1; i <= t; i++) { x = read(), y = read(); printf("%d\n", query(x, y)); } } return0; }