#include <bits/stdc++.h>
using namespace std;
struct nod {
  int y;
  long long cost;
  inline nod(int _y, long long _cost) {
    y = _y;
    cost = _cost;
  }
  inline bool operator<(const nod& c) const { return cost > c.cost; }
};
vector<nod> v[100002], T[100002];
vector<pair<int, int> > nott;
int viz[100002];
int a[22][4 * 100002 + 1], niv[4 * 100002 + 1], p[4 * 100002 + 1],
    poz[4 * 100002 + 1], lg[4 * 100002 + 1], K;
long long rdist[100002];
map<int, vector<long long> > dist;
void dfst(int nodd, int par) {
  viz[nodd] = 1;
  for (const nod& x : v[nodd]) {
    if (viz[x.y] == 0) {
      T[nodd].push_back(x);
      dfst(x.y, nodd);
    } else {
      if (x.y != par && nodd < x.y) nott.push_back(make_pair(nodd, x.y));
    }
  }
}
void dfs(int n, int lev, long long rd) {
  p[++K] = n;
  niv[K] = lev;
  poz[n] = K;
  rdist[n] = rd;
  for (vector<nod>::iterator it = T[n].begin(); it != T[n].end(); it++) {
    dfs(it->y, lev + 1, rd + it->cost);
    p[++K] = n;
    niv[K] = lev;
  }
}
int lca(int i, int j) {
  i = poz[i];
  j = poz[j];
  int l;
  if (i > j) swap(i, j);
  l = lg[j - i + 1];
  if (niv[a[l][i]] < niv[a[l][j - (1 << l) + 1]])
    return p[a[l][i]];
  else
    return p[a[l][j - (1 << l) + 1]];
}
void build_lca(int n) {
  int i, j;
  K = 0;
  dfs(1, 0, 0LL);
  n = K;
  lg[1] = 0;
  for (i = 2; i <= n; i++) lg[i] = lg[i / 2] + 1;
  for (i = 1; i <= n; i++) a[0][i] = i;
  for (i = 1; (1 << i) <= n; i++)
    for (j = 1; j <= n - (1 << i) + 1; j++) {
      a[i][j] = a[i - 1][j];
      if (niv[a[i][j]] > niv[a[i - 1][j + (1 << (i - 1))]])
        a[i][j] = a[i - 1][j + (1 << (i - 1))];
    }
}
vector<long long> dijkstra(int x, const int n) {
  priority_queue<nod> c;
  c.push(nod(x, 0));
  memset(viz, 0, sizeof(viz));
  vector<long long> d;
  for (int i = 0; i <= n; i++) {
    d.push_back((1LL << 62));
  }
  d[x] = 0;
  while (!c.empty()) {
    x = c.top().y;
    c.pop();
    if (viz[x] == 0) {
      viz[x] = 1;
      for (const nod& y : v[x]) {
        if (d[y.y] > (d[x] + y.cost)) {
          d[y.y] = d[x] + y.cost;
          c.push(nod(y.y, d[y.y]));
        }
      }
    }
  }
  return d;
}
void build_paths(const int x, const int n) {
  if (dist.find(x) != dist.end()) {
    return;
  }
  dist[x] = dijkstra(x, n);
}
void build_dijkstra(const int n) {
  for (const pair<int, int>& m : nott) {
    build_paths(m.first, n);
    build_paths(m.second, n);
  }
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    int x, y, cost;
    scanf("%d%d%d", &x, &y, &cost);
    v[x].push_back(nod(y, cost));
    v[y].push_back(nod(x, cost));
  }
  memset(viz, 0, sizeof(viz));
  dfst(1, 0);
  assert(n - 1 + (int)nott.size() == m);
  build_lca(n);
  build_dijkstra(n);
  int q;
  scanf("%d", &q);
  for (int i = 1; i <= q; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    int l = lca(x, y);
    long long sol = rdist[x] + rdist[y] - 2LL * rdist[l];
    for (const pair<int, int>& m : nott) {
      sol = min(sol, dist[m.first][x] + dist[m.first][y]);
      sol = min(sol, dist[m.second][x] + dist[m.second][y]);
    }
    cout << sol << '\n';
  }
  return 0;
}
