#include <bits/stdc++.h>
using namespace std;
const int MAGIC = 300;
const int N = (int)1e5;
vector<pair<int, int> > graph[N];
vector<int> result[N];
vector<int> vertices[N];
int visit[N];
struct DisjointSet {
  vector<int> label;
  DisjointSet(int n) { label.assign(n, -1); }
  int get(int u) { return label[u] < 0 ? u : label[u] = get(label[u]); }
  void join(int u, int v) {
    u = get(u);
    v = get(v);
    if (u == v) return;
    if (label[u] < label[v]) swap(u, v);
    label[v] += label[u];
    label[u] = v;
  }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  int n;
  cin >> n;
  int m;
  cin >> m;
  for (int i = 0; i < m; ++i) {
    int u;
    cin >> u;
    --u;
    int v;
    cin >> v;
    --v;
    int c;
    cin >> c;
    --c;
    graph[u].emplace_back(c, v);
    graph[v].emplace_back(c, u);
    vertices[c].emplace_back(u);
    vertices[c].emplace_back(v);
  }
  for (int u = 0; u < n; ++u) {
    sort(graph[u].begin(), graph[u].end());
  }
  for (int c = 0; c < m; ++c) {
    sort(vertices[c].begin(), vertices[c].end());
    vertices[c].erase(unique(vertices[c].begin(), vertices[c].end()),
                      vertices[c].end());
  }
  vector<DisjointSet> sets;
  int visitTime = 0;
  for (int c = 0; c < m; ++c) {
    if (vertices[c].size() > MAGIC) {
      sets.emplace_back(n);
      for (int u : vertices[c]) {
        int first =
            lower_bound(graph[u].begin(), graph[u].end(), make_pair(c, 0)) -
            graph[u].begin();
        while (first < (int)graph[u].size() && graph[u][first].first == c) {
          sets.back().join(u, graph[u][first].second);
          ++first;
        }
      }
    } else {
      ++visitTime;
      for (int u : vertices[c])
        if (visit[u] != visitTime) {
          vector<int> order = {u};
          visit[u] = visitTime;
          for (int i = 0; i < (int)order.size(); ++i) {
            int v = order[i];
            int first =
                lower_bound(graph[v].begin(), graph[v].end(), make_pair(c, 0)) -
                graph[v].begin();
            while (first < (int)graph[v].size() && graph[v][first].first == c) {
              int w = graph[v][first].second;
              if (visit[w] != visitTime) {
                visit[w] = visitTime;
                order.emplace_back(w);
              }
              ++first;
            }
          }
          sort(order.begin(), order.end());
          for (int i = 0; i < (int)order.size(); ++i) {
            for (int j = i + 1; j < (int)order.size(); ++j) {
              result[order[i]].emplace_back(order[j]);
            }
          }
        }
    }
  }
  for (int u = 0; u < n; ++u) {
    sort(result[u].begin(), result[u].end());
  }
  auto getLength = [](pair<vector<int>::iterator, vector<int>::iterator> x) {
    return x.second - x.first;
  };
  int numQueries;
  cin >> numQueries;
  for (int q = 0; q < numQueries; ++q) {
    int u;
    cin >> u;
    --u;
    int v;
    cin >> v;
    --v;
    if (u > v) swap(u, v);
    int answer = getLength(equal_range(result[u].begin(), result[u].end(), v));
    for (auto &aSet : sets) answer += aSet.get(u) == aSet.get(v) ? 1 : 0;
    printf("%d\n", answer);
  }
  return 0;
}
