Mr. Kitayuta has just bought an undirected graph with n vertices and m edges. The vertices of the graph are numbered from 1 to n. Each edge, namely edge i, has a color ci, connecting vertex ai and bi.

Mr. Kitayuta wants you to process the following q queries.

In the i-th query, he gives you two integers - ui and vi.

Find the number of the colors that satisfy the following condition: the edges of that color connect vertex ui and vertex vi directly or indirectly.

Input

The first line of the input contains space-separated two integers - n and m(2 ≤ n ≤ 105, 1 ≤ m ≤ 105), denoting the number of the vertices and the number of the edges, respectively.

The next m lines contain space-separated three integers - ai, bi(1 ≤ ai < bi ≤ n) and ci(1 ≤ ci ≤ m). Note that there can be multiple edges between two vertices. However, there are no multiple edges of the same color between two vertices, that is, if i ≠ j, (ai, bi, ci) ≠ (aj, bj, cj).

The next line contains a integer- q(1 ≤ q ≤ 105), denoting the number of the queries.

Then follows q lines, containing space-separated two integers - ui and vi(1 ≤ ui, vi ≤ n). It is guaranteed that ui ≠ vi.

Output

For each query, print the answer in a separate line.

Examples

Input

4 5
1 2 1
1 2 2
2 3 1
2 3 3
2 4 3
3
1 2
3 4
1 4


Output

2
1
0


Input

5 7
1 5 1
2 5 1
3 5 1
4 5 1
1 2 2
2 3 2
3 4 2
5
1 5
5 1
2 5
1 5
1 4


Output

1
1
1
1
2

Note

Let's consider the first sample. 

<image> The figure above shows the first sample. 

  * Vertex 1 and vertex 2 are connected by color 1 and 2. 
  * Vertex 3 and vertex 4 are connected by color 3. 
  * Vertex 1 and vertex 4 are not connected by any single color. 
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int M = 1e5 + 5;
const int Q = 1e5 + 5;
const int MAXN = 2 * M;
struct unionFind {
  int par[MAXN];
  int size[MAXN];
  void init() {
    for (int i = 0; i < MAXN; i++) {
      par[i] = -1;
      size[i] = 1;
    }
  }
  int root(int a) {
    if (par[a] == -1) {
      return a;
    }
    return par[a] = root(par[a]);
  }
  void unite(int a, int b) {
    a = root(a);
    b = root(b);
    if (a == b) {
      return;
    }
    if (size[a] < size[b]) {
      swap(a, b);
    }
    par[b] = a;
    size[a] += size[b];
  }
  bool same(int a, int b) { return root(a) == root(b); }
};
unionFind u;
int n, m, q;
vector<int> graph[N];
pair<pair<int, int>, int> cmp[M];
int deg[N];
int getpos(const vector<int> &a, int indx, int c) {
  return deg[indx] + lower_bound(a.begin(), a.end(), c) - a.begin();
}
int main() {
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    graph[a].push_back(c);
    graph[b].push_back(c);
    pair<int, int> tmp = {a, b};
    cmp[i] = {tmp, c};
  }
  for (int i = 0; i < n; i++) {
    sort(graph[i].begin(), graph[i].end());
    graph[i].erase(unique(graph[i].begin(), graph[i].end()), graph[i].end());
    deg[i + 1] = deg[i] + graph[i].size();
  }
  u.init();
  for (int i = 0; i < m; i++) {
    int a = cmp[i].first.first;
    int b = cmp[i].first.second;
    int c = cmp[i].second;
    int A = getpos(graph[a], a, c);
    int B = getpos(graph[b], b, c);
    u.unite(A, B);
  }
  int q;
  cin >> q;
  map<pair<int, int>, int> memoize;
  for (int i = 0; i < q; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    int res = 0;
    if (graph[a].size() > graph[b].size()) {
      swap(a, b);
    }
    pair<int, int> p = {a, b};
    if (memoize.count(p)) {
      res = memoize[p];
    } else {
      for (int j = 0; j < graph[a].size(); j++) {
        int c = graph[a][j];
        if (binary_search(graph[b].begin(), graph[b].end(), c)) {
          int tmp = getpos(graph[b], b, c);
          if (u.same(tmp, deg[a] + j)) {
            res++;
          }
        }
      }
      memoize[p] = res;
    }
    cout << res << endl;
  }
}
