#include<iostream>
#include<algorithm>
#include<vector>
const int sz = 1e4 + 10;
const int lgsz = std::__lg(sz) + 1;
int arr[sz], rnk[sz], n, m, f[lgsz][sz];
struct Edge {
int u, v, w;
bool operator<(const Edge &a) const {
return w > a.w;
}
} Graph[sz * 6];
struct edge {
int nxt, to, w;
} graph[sz << 1];
int hpp, head[sz];
void addEdge(int from, int to, int w) {
graph[++hpp] = edge{head[from], to, w};
head[from] = hpp;
}
struct UFS {
std::vector<int> fa, ssz;
void clear(int n) {
fa.assign(n + 1, 0), ssz.assign(n + 1, 1);
for (int i = 1; i <= n; i++) fa[i] = i;
}
int find(int u) {
if (fa[u] == u) return u;
return fa[u] = find(fa[u]);
}
bool merge(int u, int v) {
int fu = find(u), fv = find(v);
if (fu == fv) return false;
if (ssz[fu] > ssz[fv]) std::swap(fu, fv);
fa[fu] = fv, ssz[fv] += ssz[fu];
return true;
}
} ufs, graphChecker;
void kruskal() {
std::sort(Graph + 1, Graph + m + 1);
for (int i = 1; i <= m; i++) {
int u = Graph[i].u, v = Graph[i].v;
if (!ufs.merge(u, v)) continue;
addEdge(u, v, Graph[i].w);
addEdge(v, u, Graph[i].w);
}
}
int hson[sz], ssz[sz], dfn[sz], dep[sz], dpp, top[sz], fa[sz];
void buildDFS(int u, int fau) {
dep[u] = dep[fau] + 1, ssz[u] = 1, fa[u] = fau;
for (int p = head[u]; p; p = graph[p].nxt) {
int v = graph[p].to;
arr[v] = graph[p].w;
if (v == fau) continue;
buildDFS(v, u);
ssz[u] += ssz[v];
if (ssz[v] > ssz[hson[u]]) hson[u] = v;
}
}
void chainDFS(int u, int t) {
top[u] = t, dfn[u] = ++dpp, rnk[dpp] = u;
if (!hson[u]) return;
chainDFS(hson[u], t);
for (int p = head[u]; p; p = graph[p].nxt) {
int v = graph[p].to;
if (v == hson[u] || v == fa[u]) continue;
chainDFS(v, v);
}
}
int queryMin(int l, int r) {
int lg = std::__lg(r - l + 1);
return std::min(f[lg][l], f[lg][r - (1 << lg) + 1]);
}
int query(int u, int v) {
int res = 0x3fffffff;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) std::swap(u, v);
res = std::min(res, queryMin(dfn[top[u]], dfn[u]));
u = fa[top[u]];
}
if (dfn[u] > dfn[v]) std::swap(u, v);
res = std::min(res, queryMin(dfn[u], dfn[v]));
return res;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> m;
ufs.clear(n), graphChecker.clear(n);
for (int i = 1; i <= m; i++) {
std::cin >> Graph[i].u >> Graph[i].v >> Graph[i].w;
graphChecker.merge(Graph[i].u, Graph[i].v);
}
for (int i = 1; i <= n; i++)
if (graphChecker.merge(1, i))
Graph[++m] = Edge{1, i, -1};
kruskal();
buildDFS(1, 0);
arr[1] = 0x3fffffff;
chainDFS(1, 1);
for (int i = 1; i <= n; i++)
f[0][i] = arr[rnk[i]];
for (int i = 1; i <= std::__lg(n); i++)
for (int j = 1; j + (1 << i) - 1 <= n; j++)
f[i][j] = std::min(f[i - 1][j], f[i - 1][j + (1 << i - 1)]);
int q;
std::cin >> q;
while (q--) {
int u, v;
std::cin >> u >> v;
std::cout << query(u, v) << "\n";
}
return 0;
}