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. 

import java.util.*;
import java.io.*;

public class Codeforces {
    
    InputStream is;
    PrintWriter out;
    String INPUT = "";
    class Graph
    {
        int V; 
        LinkedList<Integer> adj[];
        boolean  visited[];
        Graph(int V) 
        { 
            this.V = V;
            adj = new LinkedList[V];
            visited=new boolean[V];
            for(int i = 0; i < V ; i++){ 
                adj[i] = new LinkedList<>(); 
                visited[i]=false;
            } 
        } 
        void addEdge(int s, int d){
            adj[s].add(d);
            adj[d].add(s);
        }
        int dfs(int s,int d,Dsu uf,int c) {
            visited[s] = true;
            for (int u : adj[s]) {
                if (!visited[u]&&uf.root(s)==uf.root(u)){
                    dfs(u,d,uf,c);
                    if(u==d){
                        c++;
                        return c;
                    }
                }
            }
            return c;
        } 
    }


//----------------------------------------------------------------------------------------------------//
    void solve() {
        int n=ni();
        int m=ni();
        Dsu uf[]=new Dsu[100];
        for (int i = 0; i < 100; i++) {
            uf[i]=new Dsu(n);
        }
        for (int i = 0; i < m; i++) {
            int a=ni()-1;
            int b=ni()-1;
            int c=ni()-1;
            uf[c].union(a, b);
        }
        int q=ni();
        for (int i = 0; i < q; i++) {
            int s=ni()-1;
            int d=ni()-1;
            int ans=0;
            for (int j = 0; j < 100; j++) {
                if(uf[j].find(s, d))ans++;
            }
            out.println(ans);
        }
        
    }

//----------------------------------------------------------------------------------------------------//
    boolean isPrime(int n) {
        if (n <= 1) {
            return false;
        }
        for (int i = 2; i <= (int) Math.sqrt(n); i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
    
    Vector<Integer> sieveOfEratosthenes(int n) {
        boolean[] prime = new boolean[n + 1];
        for (int i = 0; i < n; i++) {
            prime[i] = true;
        }
        for (int p = 2; p * p <= n; p++) {
            if (prime[p] == true) {
                for (int j = p * p; j <= n; j += p) {
                    prime[j] = false;
                }
            }
        }
        Vector<Integer> v = new Vector<>();
        for (int i = 2; i <= n; i++) {
            if (prime[i]) {
                v.add(i);
            }
        }
        return v;
    }
    
    void swap(int a[], int l, int r) {
        int temp = a[l];
        a[l] = a[r];
        a[r] = temp;
    }
    
    long nCr(int n, int k) {
        long C[] = new long[k + 1];
        // nC0 is 1 
        C[0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = Math.min(i, k); j > 0; j--) {
                C[j] = C[j] + C[j - 1];
            }
        }
        return C[k];
    }
    
    int gcd(int s, int l) {
        if (s == 0) {
            return l;
        }
        
        return gcd(l % s, s);
    }
    
    int power(long x, long y, int m) { //log(y)
        if (y == 0) {
            return 1;
        }
        long p = power(x, y / 2, m) % m;
        p = (p * p) % m;
        return (int) ((y % 2 == 0) ? p : (x * p) % m);
    }
    
    int modInverse(int a, int m) // O(Log m) whem m is prime (fermat's little theorem)
    {        
        if (gcd(a, m) != 1) {
            return -1;
        } else {            
            return power(a, m - 2, m);            
        }        
    }    
    
    public HashMap<Integer, Integer> sortByValue(HashMap<Integer, Integer> hm) {
        // Create a list from elements of HashMap 
        List<Map.Entry<Integer, Integer>> list
                = new LinkedList<>(hm.entrySet());

        //->change o1,o2 for reverseorder
        Collections.sort(list, (Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) -> (o1.getValue()).compareTo(o2.getValue()));

        // put data from sorted list to hashmap  
        HashMap<Integer, Integer> temp = new LinkedHashMap<>();
        list.forEach((aa) -> {
            temp.put(aa.getKey(), aa.getValue());
        });
        return temp;
    }
    
    void run() throws Exception {
        is = System.in;//oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        out = new PrintWriter(System.out);
        
        long s = System.currentTimeMillis();
        solve();
        out.flush();
        tr(System.currentTimeMillis() - s + "ms");
    }
    
    public static void main(String[] args) throws Exception {
        new Codeforces().run();
    }
    
    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;
    
    private int readByte() {
        if (lenbuf == -1) {
            throw new InputMismatchException();
        }
        if (ptrbuf >= lenbuf) {
            ptrbuf = 0;
            try {
                lenbuf = is.read(inbuf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (lenbuf <= 0) {
                return -1;
            }
        }
        return inbuf[ptrbuf++];
    }
    
    private boolean isSpaceChar(int c) {
        return !(c >= 33 && c <= 126);
    }
    
    private int skip() {
        int b;
        while ((b = readByte()) != -1 && isSpaceChar(b));
        return b;
    }
    
    private double nd() {
        return Double.parseDouble(ns());
    }
    
    private char nc() {
        return (char) skip();
    }
    
    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    
    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while (p < n && !(isSpaceChar(b))) {
            buf[p++] = (char) b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }
    
    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for (int i = 0; i < n; i++) {
            map[i] = ns(m);
        }
        return map;
    }
    
    private int[] na(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = ni();
        }
        return a;
    }
    
    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        
        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    
    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        
        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    
    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
    
    private void tr(Object... o) {
        if (!oj) {
            System.out.println(Arrays.deepToString(o));
            
        }
    }
    
    class Pair {

        /*SORTING PAIRS BY COMPARING Y OF PAIR.
    Pair[] p=new Pair[n];
    p[i]=new Pair(i,ni());
    Arrays.sort(p,( p1, p2) -> {return p1.y-p2.y;});
         */
        int x;
        int y;
        
        Pair(int u, int v) {
            x = u;
            y = v;
        }
        
        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (!(o instanceof Pair)) {
                return false;
            }
            Pair key = (Pair) o;
            return x == key.x && y == key.y;
        }
        
        @Override
        public int hashCode() {
            int result = x;
            result = 31 * result + y;
            return result;
        }
        
    }
    
    class Dsu {

        int par[];
        int size[];
        int cnt;
        Set<Integer> roots = new HashSet<>();
        //boolean belongs[];
        
        Dsu(int n) {
            cnt = n;//cnt=0;
            par = new int[n];
            size = new int[n];
            //belongs=new boolean[n];
            for (int i = 0; i < n; i++) {
                par[i] = i;
                size[i] = 1;
                roots.add(i);
                //belongs[i]=false;
            }
        }
        
        int root(int i) {
            if (i == par[i]) {
                return i;
            }
            return par[i] = root(par[i]);
        }
        
        boolean find(int p, int q) {
            return root(p) == root(q);
        }
        
        void union(int p, int q) {
            int a = root(p);
            int b = root(q);
            if (a != b) {
                cnt--;
            }
            /*if(!belongs[p]&&!belongs[q])cnt++;
            else if(belongs[p]&&belongs[q]){
                if(a!=b)cnt--;
            }
            belongs[p]=belongs[q]=true;*/
            if (a == b) {
                return;
            }
            if (size[a] < size[b]) {
                int temp = a;
                a = b;
                b = temp;
            }
            par[b] = a;
            size[a] += size[b];
            roots.add(a);
            if (roots.contains(b)) {
                roots.remove(b);
            }
        }
        
        Set<Integer> getRoots() {
            return roots;
        }
        
        int count() {            
            return cnt;
        }
        
    }
}
//isPrime(int)
//Vector<Integer> sieveOfEratosthenes(int n){PRIME NO <=n}
//swap(arr,i,j)
//HashMap sortByValue(map);
//long comb=nCr(5,2);
//int gcd(s,l);
//Pair p=new Pair(x,y);
// Dsu dsu=new Dsu(n);
