#include <bits/stdc++.h>
using namespace std;
template <class c>
struct rge {
  c b, e;
};
template <class c>
rge<c> range(c i, c j) {
  return {i, j};
}
struct printer {
  ~printer() { cerr << endl; }
  template <class c>
  printer& operator,(c x) {
    cerr << boolalpha << x;
    return *this;
  }
  printer& operator,(string x) {
    cerr << x;
    return *this;
  }
  template <class c, class d>
  printer& operator,(pair<c, d> x) {
    return *this, "(", x.first, ", ", x.second, ")";
  }
  template <class... d, template <class...> class c>
  printer& operator,(c<d...> x) {
    return *this, range(begin(x), end(x));
  }
  template <class c>
  printer& operator,(rge<c> x) {
    *this, "[";
    for (auto it = x.b; it != x.e; ++it) *this, (it == x.b ? "" : ", "), *it;
    return *this, "]";
  }
};
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int my_rand(int l, int r) { return uniform_int_distribution<int>(l, r)(rng); }
namespace solve {
const int lg = 20;
vector<int> who, depth;
vector<vector<int>> mx, par, g, cst;
int n;
int comp;
void init(int n_) {
  n = n_;
  g.assign(n, {});
  depth.assign(n, 0);
  cst.assign(n, {});
  par.assign(n, vector<int>(lg, -1));
  mx.assign(n, vector<int>(lg));
}
void addEdge(int u, int v, int w) {
  g[u].push_back(v);
  g[v].push_back(u);
  cst[u].push_back(w);
  cst[v].push_back(w);
}
void dfs(int u, int p, int w = 0, int d = 0) {
  who[u] = comp;
  par[u][0] = p;
  mx[u][0] = w;
  depth[u] = d;
  for (int k = 1; k < lg; k++) {
    par[u][k] = (par[u][k - 1] == -1 ? -1 : par[par[u][k - 1]][k - 1]);
    mx[u][k] =
        (par[u][k - 1] == -1 ? 0 : max(mx[u][k - 1], mx[par[u][k - 1]][k - 1]));
  }
  for (int i = 0; i < g[u].size(); i++) {
    int v = g[u][i];
    int c = cst[u][i];
    if (v == p) continue;
    dfs(v, u, c, d + 1);
  }
}
void preprocess() {
  comp = 0;
  who.assign(n, -1);
  for (int i = 0; i < n; i++) {
    if (who[i] == -1) {
      dfs(i, -1);
      ++comp;
    }
  }
}
int pathMax(int u, int v) {
  assert(u != v);
  int ans = 0;
  if (depth[u] < depth[v]) swap(u, v);
  for (int k = lg - 1; k >= 0; k--) {
    if (depth[u] - depth[v] >= (1 << k)) {
      ans = max(mx[u][k], ans);
      u = par[u][k];
    }
  }
  if (u == v) return ans;
  for (int k = lg - 1; k >= 0; k--) {
    if (par[u][k] != par[v][k]) {
      ans = max(ans, mx[u][k]);
      ans = max(ans, mx[v][k]);
      u = par[u][k];
      v = par[v][k];
    }
  }
  ans = max(ans, mx[u][0]);
  ans = max(ans, mx[v][0]);
  return ans;
}
}  // namespace solve
struct Edge {
  int u, v, w;
  bool operator<(const Edge& e) const { return w < e.w; }
};
const int N = 1e5 + 100;
int par[N];
int P(int u) { return par[u] = (par[u] ^ u ? P(par[u]) : u); }
bool Merge(int u, int v) {
  u = P(u);
  v = P(v);
  if (u == v) return false;
  par[u] = v;
  return true;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<Edge> edges(m);
  for (int i = 0; i < m; i++) {
    cin >> edges[i].u >> edges[i].v >> edges[i].w;
    edges[i].u--;
    edges[i].v--;
  }
  sort(edges.begin(), edges.end());
  solve::init(n);
  long long ans = 0;
  for (int i = 0; i < n; i++) par[i] = i;
  for (int i = 0; i < m; i++) {
    if (Merge(edges[i].u, edges[i].v)) {
      solve::addEdge(edges[i].u, edges[i].v, edges[i].w);
      ans += edges[i].w;
    }
  }
  solve::preprocess();
  int q;
  cin >> q;
  while (q--) {
    int u, v;
    cin >> u >> v;
    u--, v--;
    if (solve::comp > 2 or (solve::who[u] == solve::who[v] && solve::comp > 1))
      cout << "-1"
           << "\n";
    else {
      long long res = ans;
      if (solve::comp == 1) {
        res -= solve::pathMax(u, v);
      }
      cout << res << "\n";
    }
  }
}
