#include <bits/stdc++.h>
using namespace std;
const double EPS = -1e8;
const double Pi = acos(-1);
bool inline equ(double a, double b) { return fabs(a - b) < EPS; }
int _R(int& x) { return scanf("%d", &x); }
int _R(long long& x) { return scanf("%" PRId64, &x); }
int _R(double& x) { return scanf("%lf", &x); }
int _R(char* s) { return scanf("%s", s); }
int R() { return 0; }
template <typename T1, typename... T2>
int R(T1& x, T2&... tail) {
  int tmp = _R(x);
  return tmp + R(tail...);
}
template <typename Iter, typename F>
inline void out(Iter s, Iter e, F of) {
  bool flag = 0;
  for (Iter it = s; it != e; it++) {
    if (flag)
      printf(" ");
    else
      flag = 1;
    of(*it);
  }
  puts("");
}
const int MAXN = 1e5 + 10;
struct Edge {
  int u, v;
  long long c;
  bool operator<(const Edge& e) const { return c < e.c; }
};
int n, m;
Edge es[MAXN * 2];
struct DSJ {
  int mom[MAXN], sz[MAXN];
  void init() {
    for (int i = (1); i <= (n); i++) mom[i] = i;
  }
  int find(int x) { return mom[x] = mom[x] == x ? x : find(mom[x]); }
  void merge(int a, int b) {
    a = find(a), b = find(b);
    mom[b] = a;
  }
} dsj;
struct Tree {
  static const int LOG = 22;
  vector<pair<int, int> > g[MAXN];
  int dep[MAXN];
  int mom[LOG][MAXN], mx[LOG][MAXN];
  int sz[MAXN], root[MAXN];
  inline void adde(Edge& e) {
    g[e.u].push_back(pair<int, int>(e.v, e.c));
    g[e.v].push_back(pair<int, int>(e.u, e.c));
  }
  void dfs(int u, int p, int c, int d, int rt) {
    mom[0][u] = p;
    mx[0][u] = c;
    dep[u] = d;
    root[u] = rt;
    for (pair<int, int> e : g[u]) {
      int v, tc;
      tie(v, tc) = e;
      if (v == p) continue;
      dfs(v, u, tc, d + 1, rt);
    }
  }
  inline void predo() {
    for (int i = (1); i <= (n); i++)
      if (!dep[i]) {
        dfs(i, -1, 0, 1, i);
      }
    for (int j = (1); j <= (LOG - 1); j++)
      for (int i = (1); i <= (n); i++) {
        mom[j][i] = mom[j - 1][mom[j - 1][i]];
        mx[j][i] = max(mx[j - 1][i], mx[j - 1][mom[j - 1][i]]);
      }
    for (int i = (1); i <= (n); i++) sz[root[i]]++;
  }
  inline int lca(int a, int b) {
    if (dep[a] < dep[b]) swap(a, b);
    int jmp = dep[a] - dep[b];
    for (int k = 0; k < (LOG); k++)
      if ((jmp >> k) & 1) a = mom[k][a];
    if (a == b) return a;
    for (int k = (LOG - 1); k >= (0); k--)
      if (mom[k][a] != mom[k][b]) {
        a = mom[k][a];
        b = mom[k][b];
      }
    return mom[0][a];
  }
  inline int qry(int a, int b) {
    int anc = lca(a, b);
    int res = 0;
    {
      int jmp = dep[a] - dep[anc];
      for (int k = 0; k < (LOG); k++)
        if ((jmp >> k) & 1) {
          res = max(res, mx[k][a]);
          a = mom[k][a];
        }
    }
    {
      int jmp = dep[b] - dep[anc];
      for (int k = 0; k < (LOG); k++)
        if ((jmp >> k) & 1) {
          res = max(res, mx[k][b]);
          b = mom[k][b];
        }
    }
    return res;
  }
} tree;
int main() {
  R(n, m);
  for (int i = (1); i <= (m); i++) R(es[i].u, es[i].v, es[i].c);
  sort(es + 1, es + 1 + m);
  long long mst_cst = 0ll;
  dsj.init();
  for (int i = (1); i <= (m); i++) {
    Edge& e = es[i];
    if (dsj.find(e.u) != dsj.find(e.v)) {
      dsj.merge(e.u, e.v);
      mst_cst += e.c;
      tree.adde(e);
    }
  }
  tree.predo();
  int q;
  R(q);
  while (q--) {
    int a, b;
    R(a, b);
    if (tree.root[a] == tree.root[b]) {
      if (tree.sz[tree.root[a]] < n)
        puts("-1");
      else
        printf("%I64d\n", mst_cst - tree.qry(a, b));
    } else {
      if (tree.sz[tree.root[a]] + tree.sz[tree.root[b]] < n)
        puts("-1");
      else
        printf("%I64d\n", mst_cst);
    }
  }
}
