import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.util.Set;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author prakharjain
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        _506D solver = new _506D();
        solver.solve(1, in, out);
        out.close();
    }

    static class _506D {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();

            edge[] edges = new edge[m];

            List<Integer> majorColors = new ArrayList<>();

            for (int i = 0; i < m; i++) {
                edges[i] = new edge(in.nextInt() - 1, in.nextInt() - 1, in.nextInt() - 1);
            }

            int[] cc = new int[m];

            for (int i = 0; i < m; i++) {
                cc[edges[i].c]++;
            }

            int sqrt = 316;

            Map<Integer, DsuInteger> dsuMaj = new HashMap<>();
            Map<Integer, DSU> dsuMin = new HashMap<>();

            Set[] va = new Set[m];

            for (int i = 0; i < m; i++) {
                if (cc[i] > sqrt) {
                    majorColors.add(i);
                    DsuInteger dsu = new DsuInteger(n);
                    for (int j = 0; j < n; j++) {
                        dsu.createSet(j);
                    }
                    dsuMaj.put(i, dsu);
                } else {
                    DSU<Integer> dsu = new DSU<>();
                    dsuMin.put(i, dsu);
                    va[i] = new HashSet();
                }
            }

            for (int i = 0; i < edges.length; i++) {
                edge edge = edges[i];
                if (cc[edge.c] > sqrt) {
                    DsuInteger dsu = dsuMaj.get(edge.c);
                    dsu.mergeSets(edge.a, edge.b);
                } else {
                    va[edge.c].add(edge.a);
                    va[edge.c].add(edge.b);
                }
            }

            Map[] ma = new Map[n];

            for (int i = 0; i < n; i++) {
                ma[i] = new HashMap<Integer, Integer>();
            }

            for (int i = 0; i < m; i++) {
                if (va[i] != null) {
                    DSU<Integer> dsu = dsuMin.get(i);

                    for (int num : (Set<Integer>) va[i]) {
                        dsu.createSet(num);
                    }
                }
            }

            for (int i = 0; i < edges.length; i++) {
                edge edge = edges[i];
                if (va[edge.c] != null) {
                    DSU<Integer> dsu = dsuMin.get(edge.c);
                    dsu.mergeSets(edge.a, edge.b);
                }
            }

            for (int i = 0; i < m; i++) {
                if (va[i] != null) {
                    DSU<Integer> dsu = dsuMin.get(i);

                    for (Integer ca : (Set<Integer>) va[i]) {
                        for (Integer cb : (Set<Integer>) va[i]) {
                            if (ca < cb) {
                                int fs1 = dsu.findSet(ca);
                                int fs2 = dsu.findSet(cb);

                                if (fs1 == fs2) {
                                    int min = ca;
                                    int max = cb;

                                    ma[min].merge(max, 1, (x, y) -> (int) x + (int) y);
                                }
                            }
                        }
                    }
                }
            }

            int q = in.nextInt();

            while (q-- > 0) {
                int u = in.nextInt() - 1;
                int v = in.nextInt() - 1;

                int min = Math.min(u, v);
                int max = Math.max(u, v);

                long ans = (int) ma[min].getOrDefault(max, 0);

                for (int i = 0; i < majorColors.size(); i++) {
                    int c = majorColors.get(i);

                    DsuInteger dsu = dsuMaj.get(c);

                    int fs1 = dsu.findSet(u);
                    int fs2 = dsu.findSet(v);

                    if (fs1 == fs2) {
                        ans++;
                    }
                }

                out.println(ans);
            }
        }

        class edge {
            int a;
            int b;
            int c;

            public edge(int a, int b, int c) {
                this.a = a;
                this.b = b;
                this.c = c;
            }

        }

        class DsuInteger {
            int[] parent;
            int[] rank;
            int n;

            public DsuInteger(int n) {
                this.n = n;
                this.parent = new int[n];
                this.rank = new int[n];
            }

            int createSet(int x) {
                parent[x] = x;
                rank[x] = 0;
                return x;
            }

            int findSet(int x) {
                int par = parent[x];
                if (x != par) {
                    parent[x] = findSet(par);
                    return parent[x];
                }
                return par;
            }

            int mergeSets(int x, int y) {
                int rx = findSet(x);
                int ry = findSet(y);

                if (rx == ry) {
                    return rx;
                }

                int fp = -1;

                if (rank[rx] > rank[ry]) {
                    parent[ry] = rx;
                    fp = rx;
                } else {
                    parent[rx] = ry;
                    fp = ry;
                }

                if (rank[rx] == rank[ry]) {
                    rank[ry] = rank[ry] + 1;
                }

                return fp;
            }

        }

        class DSU<T> {
            Map<T, T> parent = new HashMap<>();
            Map<T, Integer> rank = new HashMap<>();

            T createSet(T x) {
                parent.put(x, x);
                rank.put(x, 0);
                return x;
            }

            T findSet(T x) {
                T par = parent.get(x);
                if (!x.equals(par)) {
                    parent.put(x, findSet(par));
                    return parent.get(x);
                }
                return par;
            }

            T mergeSets(T x, T y) {
                T rx = findSet(x);
                T ry = findSet(y);

                if (rx.equals(ry)) {
                    return rx;
                }

                T fp = null;

                if (rank.get(rx) > rank.get(ry)) {
                    parent.put(ry, rx);
                    fp = rx;
                } else {
                    parent.put(rx, ry);
                    fp = ry;
                }

                if (rank.get(rx).equals(rank.get(ry))) {
                    rank.put(ry, rank.get(ry) + 1);
                }

                return fp;
            }

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void println(long i) {
            writer.println(i);
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author beginner1010
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        int[] visit;
        int[] parent;
        int[] height;

        int parent(int node, int color) {
            if (visit[node] < color) {
                height[node] = 0;
                parent[node] = node;
                visit[node] = color;
                return node;
            } else if (parent[node] == node) {
                return node;
            } else {
                return parent[node] = parent(parent[node], color);
            }
        }

        void join(int a, int b, int color) {
            int parA = parent(a, color);
            int parB = parent(b, color);
            if (parA == parB) return;
            if (height[parA] > height[parB]) {
                parent[parB] = parA;
            } else {
                parent[parA] = parB;
                if (height[parA] == height[parB]) height[parB]++;
            }
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();

            ArrayList<Pair>[] edges = new ArrayList[m];
            for (int i = 0; i < m; i++) {
                edges[i] = new ArrayList<>();
            }
            for (int i = 0; i < m; i++) {
                int a = in.nextInt() - 1;
                int b = in.nextInt() - 1;
                int c = in.nextInt() - 1;
                edges[c].add(new Pair(a, b));
            }

            visit = new int[n];
            parent = new int[n];
            height = new int[n];
            HashSet<Pair>[] components = new HashSet[n];
            for (int i = 0; i < n; i++) {
                components[i] = new HashSet<>();
            }

            Arrays.fill(visit, -1);
            for (int color = 0; color < m; color++) {
                TreeSet<Integer> seenVertices = new TreeSet<>();
                for (Pair edge : edges[color]) {
                    join(edge.first, edge.second, color);
                    seenVertices.add(edge.first);
                    seenVertices.add(edge.second);
                }
                for (Integer vertex : seenVertices) {
                    components[vertex].add(new Pair(parent(vertex, color), color));
                }
            }

            HashMap<Pair, Integer> cacheQueries = new HashMap<>();
            int q = in.nextInt();
            for (int i = 0; i < q; i++) {
                int a = in.nextInt() - 1;
                int b = in.nextInt() - 1;
                if (components[a].size() > components[b].size() || (components[b].size() == components[a].size() && a > b)) {
                    a ^= b;
                    b ^= a;
                    a ^= b;
                }
                Pair query = new Pair(a, b);
                if (cacheQueries.containsKey(query)) {
                    out.println(cacheQueries.get(query));
                    continue;
                }
                int res = 0;
                for (Pair component : components[a]) {
                    if (components[b].contains(component))
                        res++;
                }
                out.println(res);
                cacheQueries.put(query, res);
            }
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }

    static class Pair implements Comparable<Pair> {
        public int first;
        public int second;

        public Pair() {
        }

        public Pair(int first, int second) {
            this.first = first;
            this.second = second;
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Pair ii = (Pair) o;

            if (first != ii.first) return false;
            if (second != ii.second) return false;

            return true;
        }

        public int hashCode() {
            int result = first;
            result = 31 * result + second;
            return result;
        }

        public int compareTo(Pair o) {
            if (first != o.first) {
                return first < o.first ? -1 : 1;
            }
            if (second != o.second) {
                return second < o.second ? -1 : 1;
            }
            return 0;
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author beginner1010
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        int[] visit;
        int[] parent;
        int[] height;

        int parent(int node, int color) {
            if (visit[node] < color) {
                height[node] = 0;
                parent[node] = node;
                visit[node] = color;
                return node;
            } else if (parent[node] == node) {
                return node;
            } else {
                return parent[node] = parent(parent[node], color);
            }
        }

        void join(int a, int b, int color) {
            int parA = parent(a, color);
            int parB = parent(b, color);
            if (parA == parB) return;
            if (height[parA] > height[parB]) {
                parent[parB] = parA;
            } else {
                parent[parA] = parB;
                if (height[parA] == height[parB]) height[parB]++;
            }
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();

            ArrayList<Pair>[] edges = new ArrayList[m];
            for (int i = 0; i < m; i++) {
                edges[i] = new ArrayList<>();
            }
            for (int i = 0; i < m; i++) {
                int a = in.nextInt() - 1;
                int b = in.nextInt() - 1;
                int c = in.nextInt() - 1;
                edges[c].add(new Pair(a, b));
            }

            visit = new int[n];
            parent = new int[n];
            height = new int[n];
            HashSet<Pair>[] components = new HashSet[n];
            for (int i = 0; i < n; i++) {
                components[i] = new HashSet<>();
            }

            Arrays.fill(visit, -1);
            for (int color = 0; color < m; color++) {
                TreeSet<Integer> seenVertices = new TreeSet<>();
                for (Pair edge : edges[color]) {
                    join(edge.first, edge.second, color);
                    seenVertices.add(edge.first);
                    seenVertices.add(edge.second);
                }
                for (Integer vertex : seenVertices) {
                    components[vertex].add(new Pair(parent(vertex, color), color));
                }
            }

            HashMap<Pair, Integer> cacheQueries = new HashMap<>();
            int q = in.nextInt();
            for (int i = 0; i < q; i++) {
                int a = in.nextInt() - 1;
                int b = in.nextInt() - 1;
                if (a > b) {
                    a ^= b;
                    b ^= a;
                    a ^= b;
                }
                Pair query = new Pair(a, b);
                if (cacheQueries.containsKey(query)) {
                    out.println(cacheQueries.get(query));
                    continue;
                }
                int res = 0;
                for (Pair component : components[a]) {
                    if (components[b].contains(component))
                        res++;
                }
                out.println(res);
                cacheQueries.put(query, res);
            }
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }

    static class Pair implements Comparable<Pair> {
        public int first;
        public int second;

        public Pair() {
        }

        public Pair(int first, int second) {
            this.first = first;
            this.second = second;
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Pair ii = (Pair) o;

            if (first != ii.first) return false;
            if (second != ii.second) return false;

            return true;
        }

        public int hashCode() {
            int result = first;
            result = 31 * result + second;
            return result;
        }

        public int compareTo(Pair o) {
            if (first != o.first) {
                return first < o.first ? -1 : 1;
            }
            if (second != o.second) {
                return second < o.second ? -1 : 1;
            }
            return 0;
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author beginner1010
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        int[] visit;
        int[] parent;
        int[] height;

        int parent(int node, int color) {
            if (visit[node] < color) {
                height[node] = 0;
                parent[node] = node;
                visit[node] = color;
                return node;
            } else if (parent[node] == node) {
                return node;
            } else {
                return parent[node] = parent(parent[node], color);
            }
        }

        void join(int a, int b, int color) {
            int parA = parent(a, color);
            int parB = parent(b, color);
            if (parA == parB) return;
            if (height[parA] > height[parB]) {
                parent[parB] = parA;
            } else {
                parent[parA] = parB;
                if (height[parA] == height[parB]) height[parB]++;
            }
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();

            ArrayList<Pair>[] edges = new ArrayList[m];
            for (int i = 0; i < m; i++) {
                edges[i] = new ArrayList<>();
            }
            for (int i = 0; i < m; i++) {
                int a = in.nextInt() - 1;
                int b = in.nextInt() - 1;
                int c = in.nextInt() - 1;
                edges[c].add(new Pair(a, b));
            }

            visit = new int[n];
            parent = new int[n];
            height = new int[n];
            HashSet<Pair>[] components = new HashSet[n];
            for (int i = 0; i < n; i++) {
                components[i] = new HashSet<>();
            }

            Arrays.fill(visit, -1);
            for (int color = 0; color < m; color++) {
                TreeSet<Integer> seenVertices = new TreeSet<>();
                for (Pair edge : edges[color]) {
                    join(edge.first, edge.second, color);
                    seenVertices.add(edge.first);
                    seenVertices.add(edge.second);
                }
                for (Integer vertex : seenVertices) {
                    components[vertex].add(new Pair(parent(vertex, color), color));
                }
            }

            HashMap<Pair, Integer> cacheQueries = new HashMap<>();
            int q = in.nextInt();
            for (int i = 0; i < q; i++) {
                int a = in.nextInt() - 1;
                int b = in.nextInt() - 1;
                if (a > b) {
                    a ^= b;
                    b ^= a;
                    b ^= a;
                }
                Pair query = new Pair(a, b);
                if (cacheQueries.containsKey(query)) {
                    out.println(cacheQueries.get(query));
                    continue;
                }
                int res = 0;
                for (Pair component : components[a]) {
                    if (components[b].contains(component))
                        res++;
                }
                out.println(res);
                cacheQueries.put(query, res);
            }
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }

    static class Pair implements Comparable<Pair> {
        public int first;
        public int second;

        public Pair() {
        }

        public Pair(int first, int second) {
            this.first = first;
            this.second = second;
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Pair ii = (Pair) o;

            if (first != ii.first) return false;
            if (second != ii.second) return false;

            return true;
        }

        public int hashCode() {
            int result = first;
            result = 31 * result + second;
            return result;
        }

        public int compareTo(Pair o) {
            if (first != o.first) {
                return first < o.first ? -1 : 1;
            }
            if (second != o.second) {
                return second < o.second ? -1 : 1;
            }
            return 0;
        }

    }
}


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

public class D implements Runnable {
	public static void main (String[] args) {new Thread(null, new D(), "_cf", 1 << 28).start();}

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt(), m = fs.nextInt();
		int[][] edges = new int[m][5];
		int[] deg = new int[n];
		for(int i = 0; i < m; i++) {
			for(int j = 0; j < 2; j++) {
				edges[i][j] = fs.nextInt()-1;
				deg[edges[i][j]]++;
			}
			edges[i][2] = fs.nextInt();
			edges[i][3] = i;
		}
		Edge[][] adj = new Edge[n][];
		for(int i = 0; i < n; i++) {
			adj[i] = new Edge[deg[i]];
			deg[i] = 0;
		}

		for(int i = 0; i < m; i++) {
			int u = edges[i][0], v = edges[i][1];
			int color = edges[i][2];
			adj[u][deg[u]] = new Edge(v, color, i);
			adj[v][deg[v]] = new Edge(u, color, i);
			deg[u]++; deg[v]++;
		}

		int q = fs.nextInt();
		Arrays.fill(deg, 0);
		int[][] queries = new int[q][3];
		for(int i = 0; i < q; i++) {
			for(int j = 0; j < 2; j++) {
				queries[i][j] = fs.nextInt()-1;
			}
			if(queries[i][0] < queries[i][1]) {
				int temp = queries[i][0];
				queries[i][0] = queries[i][1];
				queries[i][1] = temp;
			}
			queries[i][2] = i;
		}

		for(int i = 0; i < n; i++) {
			Arrays.sort(adj[i]);
		}
		Arrays.sort(edges, (a, b) -> Integer.compare(a[2], b[2]));

		for(int i = 0; i < m; i++) edges[i][4] = i;

		boolean[] used = new boolean[m];
		int[] queue = new int[m];
		int[] visTime = new int[n];
		int curColor = 1;
		ArrayList<Integer>[] allTimes = new ArrayList[n];
		for(int i = 0; i < n; allTimes[i++] = new ArrayList<>());
		HashMap<Integer, Integer>[] maps = new HashMap[n];
		for(int i = 0; i < n; i++) maps[i] = new HashMap<>();
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < adj[i].length; j++) {
				int col = adj[i][j].color;
				if(!maps[i].containsKey(col)) maps[i].put(col, j);
			}
		}

		for(int i = 0; i < edges.length; i++) {
			int upTo = i;
			while(upTo < edges.length && edges[i][2] == edges[upTo][2]) {
				upTo++;
			}
			for(int k = i; k < upTo; k++) {
				int id = edges[k][3];
				if(used[id]) continue;
				int tail = 0;
				queue[tail++] = edges[i][0];
				queue[tail++] = edges[i][1];
				visTime[edges[i][0]] = curColor;
				visTime[edges[i][1]] = curColor;
				used[id] = true;

				for(int j = 0; j < tail; j++) {
					int u = queue[j];
					allTimes[u].add(curColor);
					int startIdx = maps[u].get(edges[i][2]);
					for(int ii = startIdx; ii < adj[u].length; ii++) {
						if(adj[u][ii].color != edges[i][2]) break;
						int v = adj[u][ii].to;
						if(visTime[v] == curColor) continue;
						if(used[adj[u][ii].id]) continue;
						visTime[v] = curColor;
						queue[tail++] = v;
						used[adj[u][ii].id] = true;
					}
				}
				curColor++;
			}
			i = --upTo;
		}

		Arrays.sort(queries, (a, b) -> Integer.compare(a[0], b[0]) == 0 ? Integer.compare(a[1], b[1]) : Integer.compare(a[0], b[0]));

		for(int i = 0; i < n; i++) {
			maps[i].clear();
			for(int j : allTimes[i]) maps[i].put(j, 0);
		}
		int[] res = new int[q];
		for(int i = 0; i < q; i++) {
			int upTo = i;
			while(upTo < q && queries[i][0] == queries[upTo][0] && queries[i][1] == queries[upTo][1]) upTo++;
			int u = queries[i][0];
			int v = queries[i][1];
			if(adj[v].length < adj[u].length) {
				int temp = v;
				v = u; u = temp;
			}
			int ret = 0;
			for(int time : allTimes[u]) {
				if(maps[v].containsKey(time)) ret++;
			}
			for(int j = i; j < upTo; j++) res[queries[j][2]] = ret;
			i = --upTo;
		}
		for(int i : res) out.println(i);

		out.close();
	}

	boolean find(ArrayList<Integer> a, int key) {
		int lo = 0, hi = a.size()-1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			int x = a.get(mid);
			if(x > key) hi = mid-1;
			else if(x < key) lo = mid+1;
			else return true;
		}
		return false;
	}

	int find(Edge[] a, int color, boolean x) {
		int lo = 0, hi = a.length-1;
		int ret = -1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			if(a[mid].color > color) {
				hi = mid-1;
			}
			else if(a[mid].color < color) {
				lo = mid+1;
			}
			else {
				ret = mid;
				if(!x) hi = mid-1;
				else lo = mid+1;
			}
		}
		return ret;
	}

	class Edge implements Comparable<Edge> {
		int to, color, id;
		Edge(int t, int c, int i) {
			to = t;
			color = c;
			id = i;
		}
		public int compareTo(Edge e) {
			return Integer.compare(color, e.color);
		}
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


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

public class D implements Runnable {
	public static void main (String[] args) {new Thread(null, new D(), "_cf", 1 << 28).start();}

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt(), m = fs.nextInt();
		int[][] edges = new int[m][5];
		int[] deg = new int[n];
		for(int i = 0; i < m; i++) {
			for(int j = 0; j < 2; j++) {
				edges[i][j] = fs.nextInt()-1;
				deg[edges[i][j]]++;
			}
			edges[i][2] = fs.nextInt();
			edges[i][3] = i;
		}
		Edge[][] adj = new Edge[n][];
		for(int i = 0; i < n; i++) {
			adj[i] = new Edge[deg[i]];
			deg[i] = 0;
		}

		for(int i = 0; i < m; i++) {
			int u = edges[i][0], v = edges[i][1];
			int color = edges[i][2];
			adj[u][deg[u]] = new Edge(v, color, i);
			adj[v][deg[v]] = new Edge(u, color, i);
			deg[u]++; deg[v]++;
		}

		int q = fs.nextInt();
		Arrays.fill(deg, 0);
		int[][] queries = new int[q][3];
		for(int i = 0; i < q; i++) {
			for(int j = 0; j < 2; j++) {
				queries[i][j] = fs.nextInt()-1;
			}
			queries[i][2] = i;
		}

		for(int i = 0; i < n; i++) {
			Arrays.sort(adj[i]);
		}
		Arrays.sort(edges, (a, b) -> Integer.compare(a[2], b[2]));

		for(int i = 0; i < m; i++) edges[i][4] = i;

		boolean[] used = new boolean[m];
		int[] queue = new int[m];
		int[] visTime = new int[n];
		int curColor = 1;
		ArrayList<Integer>[] allTimes = new ArrayList[n];
		for(int i = 0; i < n; allTimes[i++] = new ArrayList<>());
		for(int i = 0; i < edges.length; i++) {
			int upTo = i;
			while(upTo < edges.length && edges[i][2] == edges[upTo][2]) {
				upTo++;
			}
			for(int k = i; k < upTo; k++) {
				int id = edges[k][3];
				if(used[id]) continue;
				int tail = 0;
				queue[tail++] = edges[i][0];
				queue[tail++] = edges[i][1];
				visTime[edges[i][0]] = curColor;
				visTime[edges[i][1]] = curColor;
				used[id] = true;

				for(int j = 0; j < tail; j++) {
					int u = queue[j];
					allTimes[u].add(curColor);
					int startIdx = find(adj[u], edges[i][2], false);
					int endIdx = find(adj[u], edges[i][2], true);
					for(int ii = startIdx; ii <= endIdx; ii++) {
						int v = adj[u][ii].to;
						if(visTime[v] == curColor) continue;
						if(used[adj[u][ii].id]) continue;
						visTime[v] = curColor;
						queue[tail++] = v;
						used[adj[u][ii].id] = true;
					}
				}
				curColor++;
			}
			i = --upTo;
		}

		Arrays.sort(queries, (a, b) -> Integer.compare(a[0], b[0]) == 0 ? Integer.compare(a[1], b[1]) : Integer.compare(a[0], b[0]));

		int[] res = new int[q];
		for(int i = 0; i < q; i++) {
			int upTo = i;
			while(upTo < q && queries[i][0] == queries[upTo][0] && queries[i][1] == queries[upTo][1]) upTo++;
			int u = queries[i][0];
			int v = queries[i][1];
			if(adj[v].length < adj[u].length) {
				int temp = v;
				v = u; u = temp;
			}
			int ret = 0;
			for(int time : allTimes[u]) {
				if(find(allTimes[v], time)) ret++;
			}
			for(int j = i; j < upTo; j++) res[queries[j][2]] = ret;
		}
		for(int i : res) out.println(i);

		out.close();
	}

	boolean find(ArrayList<Integer> a, int key) {
		int lo = 0, hi = a.size()-1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			int x = a.get(mid);
			if(x > key) hi = mid-1;
			else if(x < key) lo = mid+1;
			else return true;
		}
		return false;
	}

	int find(Edge[] a, int color, boolean x) {
		int lo = 0, hi = a.length-1;
		int ret = -1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			if(a[mid].color > color) {
				hi = mid-1;
			}
			else if(a[mid].color < color) {
				lo = mid+1;
			}
			else {
				ret = mid;
				if(!x) hi = mid-1;
				else lo = mid+1;
			}
		}
		return ret;
	}

	class Edge implements Comparable<Edge> {
		int to, color, id;
		Edge(int t, int c, int i) {
			to = t;
			color = c;
			id = i;
		}
		public int compareTo(Edge e) {
			return Integer.compare(color, e.color);
		}
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


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

public class D implements Runnable {
	public static void main (String[] args) {new Thread(null, new D(), "_cf", 1 << 28).start();}

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt(), m = fs.nextInt();
		int[][] edges = new int[m][5];
		int[] deg = new int[n];
		for(int i = 0; i < m; i++) {
			for(int j = 0; j < 2; j++) {
				edges[i][j] = fs.nextInt()-1;
				deg[edges[i][j]]++;
			}
			edges[i][2] = fs.nextInt();
			edges[i][3] = i;
		}
		Edge[][] adj = new Edge[n][];
		for(int i = 0; i < n; i++) {
			adj[i] = new Edge[deg[i]];
			deg[i] = 0;
		}

		for(int i = 0; i < m; i++) {
			int u = edges[i][0], v = edges[i][1];
			int color = edges[i][2];
			adj[u][deg[u]] = new Edge(v, color, i);
			adj[v][deg[v]] = new Edge(u, color, i);
			deg[u]++; deg[v]++;
		}

		int q = fs.nextInt();
		int[][] queries = new int[q][3];
		for(int i = 0; i < q; i++) {
			for(int j = 0; j < 2; j++) {
				queries[i][j] = fs.nextInt()-1;
			}
			if(queries[i][0] < queries[i][1]) {
				int temp = queries[i][0];
				queries[i][0] = queries[i][1];
				queries[i][1] = temp;
			}
			queries[i][2] = i;
		}

		for(int i = 0; i < n; i++) {
			Arrays.sort(adj[i]);
		}
		Arrays.sort(edges, (a, b) -> Integer.compare(a[2], b[2]));

		for(int i = 0; i < m; i++) edges[i][4] = i;

		boolean[] used = new boolean[m];
		int[] queue = new int[m];
		int[] visTime = new int[n];
		int curColor = 1;
		ArrayList<Integer>[] allTimes = new ArrayList[n];
		for(int i = 0; i < n; allTimes[i++] = new ArrayList<>());
		HashMap<Integer, Integer>[] maps = new HashMap[n];
		for(int i = 0; i < n; i++) maps[i] = new HashMap<>();
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < adj[i].length; j++) {
				int col = adj[i][j].color;
				if(!maps[i].containsKey(col)) maps[i].put(col, j);
			}
		}

		for(int i = 0; i < edges.length; i++) {
			int upTo = i;
			while(upTo < edges.length && edges[i][2] == edges[upTo][2]) {
				upTo++;
			}
			for(int k = i; k < upTo; k++) {
				int id = edges[k][3];
				if(used[id]) continue;
				int tail = 0;
				queue[tail++] = edges[k][0];
				queue[tail++] = edges[k][1];
				visTime[edges[k][0]] = curColor;
				visTime[edges[k][1]] = curColor;
				used[id] = true;

				for(int j = 0; j < tail; j++) {
					int u = queue[j];
					allTimes[u].add(curColor);
					int startIdx = maps[u].get(edges[i][2]);
					for(int ii = startIdx; ii < adj[u].length; ii++) {
						if(adj[u][ii].color != edges[i][2]) break;
						int v = adj[u][ii].to;
						if(used[adj[u][ii].id]) continue;
						used[adj[u][ii].id] = true;
						if(visTime[v] == curColor) continue;
						visTime[v] = curColor;
						queue[tail++] = v;
					}
				}
				curColor++;
			}
			i = --upTo;
		}

		Arrays.sort(queries, (a, b) -> Integer.compare(a[0], b[0]) == 0 ? Integer.compare(a[1], b[1]) : Integer.compare(a[0], b[0]));

		for(int i = 0; i < n; i++) {
			maps[i].clear();
			for(int j : allTimes[i]) maps[i].put(j, 0);
		}
		int[] res = new int[q];
		for(int i = 0; i < q; i++) {
			int upTo = i;
			while(upTo < q && queries[i][0] == queries[upTo][0] && queries[i][1] == queries[upTo][1]) upTo++;
			int u = queries[i][0];
			int v = queries[i][1];
			if(adj[v].length < adj[u].length) {
				int temp = v;
				v = u; u = temp;
			}
			int ret = 0;
			for(int time : allTimes[u]) {
				if(maps[v].containsKey(time)) ret++;
			}
			for(int j = i; j < upTo; j++) res[queries[j][2]] = ret;
			i = --upTo;
		}
		for(int i : res) out.println(i);

		out.close();
	}

	boolean find(ArrayList<Integer> a, int key) {
		int lo = 0, hi = a.size()-1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			int x = a.get(mid);
			if(x > key) hi = mid-1;
			else if(x < key) lo = mid+1;
			else return true;
		}
		return false;
	}

	int find(Edge[] a, int color, boolean x) {
		int lo = 0, hi = a.length-1;
		int ret = -1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			if(a[mid].color > color) {
				hi = mid-1;
			}
			else if(a[mid].color < color) {
				lo = mid+1;
			}
			else {
				ret = mid;
				if(!x) hi = mid-1;
				else lo = mid+1;
			}
		}
		return ret;
	}

	class Edge implements Comparable<Edge> {
		int to, color, id;
		Edge(int t, int c, int i) {
			to = t;
			color = c;
			id = i;
		}
		public int compareTo(Edge e) {
			return Integer.compare(color, e.color);
		}
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


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

public class D implements Runnable {
	public static void main (String[] args) {new Thread(null, new D(), "_cf", 1 << 28).start();}

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt(), m = fs.nextInt();
		int[][] edges = new int[m][5];
		int[] deg = new int[n];
		for(int i = 0; i < m; i++) {
			for(int j = 0; j < 2; j++) {
				edges[i][j] = fs.nextInt()-1;
				deg[edges[i][j]]++;
			}
			edges[i][2] = fs.nextInt();
			edges[i][3] = i;
		}
		Edge[][] adj = new Edge[n][];
		for(int i = 0; i < n; i++) {
			adj[i] = new Edge[deg[i]];
			deg[i] = 0;
		}

		for(int i = 0; i < m; i++) {
			int u = edges[i][0], v = edges[i][1];
			int color = edges[i][2];
			adj[u][deg[u]] = new Edge(v, color, i);
			adj[v][deg[v]] = new Edge(u, color, i);
			deg[u]++; deg[v]++;
		}

		int q = fs.nextInt();
		int[][] queries = new int[q][3];
		for(int i = 0; i < q; i++) {
			for(int j = 0; j < 2; j++) {
				queries[i][j] = fs.nextInt()-1;
			}
			if(queries[i][0] < queries[i][1]) {
				int temp = queries[i][0];
				queries[i][0] = queries[i][1];
				queries[i][1] = temp;
			}
			queries[i][2] = i;
		}

		for(int i = 0; i < n; i++) {
			Arrays.sort(adj[i]);
		}
		Arrays.sort(edges, (a, b) -> Integer.compare(a[2], b[2]));

		for(int i = 0; i < m; i++) edges[i][4] = i;

		boolean[] used = new boolean[m];
		int[] queue = new int[2*Math.max(n, m)];
		int[] visTime = new int[n];
		int curColor = 1;
		ArrayList<Integer>[] allTimes = new ArrayList[n];
		for(int i = 0; i < n; allTimes[i++] = new ArrayList<>());
		HashMap<Integer, Integer>[] maps = new HashMap[n];
		for(int i = 0; i < n; i++) maps[i] = new HashMap<>();
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < adj[i].length; j++) {
				int col = adj[i][j].color;
				if(!maps[i].containsKey(col)) maps[i].put(col, j);
			}
		}

		for(int i = 0; i < edges.length; i++) {
			int upTo = i;
			while(upTo < edges.length && edges[i][2] == edges[upTo][2]) {
				upTo++;
			}
			for(int k = i; k < upTo; k++) {
				int id = edges[k][3];
				if(used[id]) continue;
				int tail = 0;
				queue[tail++] = edges[k][0];
				queue[tail++] = edges[k][1];
				visTime[edges[k][0]] = curColor;
				visTime[edges[k][1]] = curColor;
				used[id] = true;

				for(int j = 0; j < tail; j++) {
					int u = queue[j];
					allTimes[u].add(curColor);
					int startIdx = maps[u].get(edges[i][2]);
					for(int ii = startIdx; ii < adj[u].length; ii++) {
						if(adj[u][ii].color != edges[i][2]) break;
						int v = adj[u][ii].to;
						if(used[adj[u][ii].id]) continue;
						used[adj[u][ii].id] = true;
						if(visTime[v] == curColor) continue;
						visTime[v] = curColor;
						queue[tail++] = v;
					}
				}
				curColor++;
			}
			i = --upTo;
		}

		Arrays.sort(queries, (a, b) -> Integer.compare(a[0], b[0]) == 0 ? Integer.compare(a[1], b[1]) : Integer.compare(a[0], b[0]));

		for(int i = 0; i < n; i++) {
			maps[i].clear();
			for(int j : allTimes[i]) maps[i].put(j, 0);
		}
		int[] res = new int[q];
		for(int i = 0; i < q; i++) {
			int upTo = i;
			while(upTo < q && queries[i][0] == queries[upTo][0] && queries[i][1] == queries[upTo][1]) upTo++;
			int u = queries[i][0];
			int v = queries[i][1];
			if(adj[v].length < adj[u].length) {
				int temp = v;
				v = u; u = temp;
			}
			int ret = 0;
			for(int time : allTimes[u]) {
				if(maps[v].containsKey(time)) ret++;
			}
			for(int j = i; j < upTo; j++) res[queries[j][2]] = ret;
			i = --upTo;
		}
		for(int i : res) out.println(i);

		out.close();
	}

	boolean find(ArrayList<Integer> a, int key) {
		int lo = 0, hi = a.size()-1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			int x = a.get(mid);
			if(x > key) hi = mid-1;
			else if(x < key) lo = mid+1;
			else return true;
		}
		return false;
	}

	int find(Edge[] a, int color, boolean x) {
		int lo = 0, hi = a.length-1;
		int ret = -1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			if(a[mid].color > color) {
				hi = mid-1;
			}
			else if(a[mid].color < color) {
				lo = mid+1;
			}
			else {
				ret = mid;
				if(!x) hi = mid-1;
				else lo = mid+1;
			}
		}
		return ret;
	}

	class Edge implements Comparable<Edge> {
		int to, color, id;
		Edge(int t, int c, int i) {
			to = t;
			color = c;
			id = i;
		}
		public int compareTo(Edge e) {
			return Integer.compare(color, e.color);
		}
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


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

public class D implements Runnable {
	public static void main (String[] args) {new Thread(null, new D(), "_cf", 1 << 28).start();}

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt(), m = fs.nextInt();
		int[][] edges = new int[m][5];
		int[] deg = new int[n];
		for(int i = 0; i < m; i++) {
			for(int j = 0; j < 2; j++) {
				edges[i][j] = fs.nextInt()-1;
				deg[edges[i][j]]++;
			}
			edges[i][2] = fs.nextInt();
			edges[i][3] = i;
		}
		Edge[][] adj = new Edge[n][];
		for(int i = 0; i < n; i++) {
			adj[i] = new Edge[deg[i]];
			deg[i] = 0;
		}

		for(int i = 0; i < m; i++) {
			int u = edges[i][0], v = edges[i][1];
			int color = edges[i][2];
			adj[u][deg[u]] = new Edge(v, color, i);
			adj[v][deg[v]] = new Edge(u, color, i);
			deg[u]++; deg[v]++;
		}

		int q = fs.nextInt();
		Arrays.fill(deg, 0);
		int[][] queries = new int[q][3];
		for(int i = 0; i < q; i++) {
			for(int j = 0; j < 2; j++) {
				queries[i][j] = fs.nextInt()-1;
			}
			queries[i][2] = i;
		}

		for(int i = 0; i < n; i++) {
			Arrays.sort(adj[i]);
		}
		Arrays.sort(edges, (a, b) -> Integer.compare(a[2], b[2]));

		for(int i = 0; i < m; i++) edges[i][4] = i;

		boolean[] used = new boolean[m];
		int[] queue = new int[m];
		int[] visTime = new int[n];
		int curColor = 1;
		ArrayList<Integer>[] allTimes = new ArrayList[n];
		for(int i = 0; i < n; allTimes[i++] = new ArrayList<>());
		HashMap<Integer, Integer>[] maps = new HashMap[n];
		for(int i = 0; i < n; i++) maps[i] = new HashMap<>();
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < adj[i].length; j++) {
				int col = adj[i][j].color;
				if(!maps[i].containsKey(col)) maps[i].put(col, j);
			}
		}

		for(int i = 0; i < edges.length; i++) {
			int upTo = i;
			while(upTo < edges.length && edges[i][2] == edges[upTo][2]) {
				upTo++;
			}
			for(int k = i; k < upTo; k++) {
				int id = edges[k][3];
				if(used[id]) continue;
				int tail = 0;
				queue[tail++] = edges[i][0];
				queue[tail++] = edges[i][1];
				visTime[edges[i][0]] = curColor;
				visTime[edges[i][1]] = curColor;
				used[id] = true;

				for(int j = 0; j < tail; j++) {
					int u = queue[j];
					allTimes[u].add(curColor);
					int startIdx = maps[u].get(edges[i][2]);
					for(int ii = startIdx; ii < adj[u].length; ii++) {
						if(adj[u][ii].color != edges[i][2]) break;
						int v = adj[u][ii].to;
						if(visTime[v] == curColor) continue;
						if(used[adj[u][ii].id]) continue;
						visTime[v] = curColor;
						queue[tail++] = v;
						used[adj[u][ii].id] = true;
					}
				}
				curColor++;
			}
			i = --upTo;
		}

		Arrays.sort(queries, (a, b) -> Integer.compare(a[0], b[0]) == 0 ? Integer.compare(a[1], b[1]) : Integer.compare(a[0], b[0]));

		for(int i = 0; i < n; i++) {
			maps[i].clear();
			for(int j : allTimes[i]) maps[i].put(j, 0);
		}
		int[] res = new int[q];
		for(int i = 0; i < q; i++) {
			int upTo = i;
			while(upTo < q && queries[i][0] == queries[upTo][0] && queries[i][1] == queries[upTo][1]) upTo++;
			int u = queries[i][0];
			int v = queries[i][1];
			if(adj[v].length < adj[u].length) {
				int temp = v;
				v = u; u = temp;
			}
			int ret = 0;
			for(int time : allTimes[u]) {
				if(maps[v].containsKey(time)) ret++;
			}
			for(int j = i; j < upTo; j++) res[queries[j][2]] = ret;
			i = --upTo;
		}
		for(int i : res) out.println(i);

		out.close();
	}

	boolean find(ArrayList<Integer> a, int key) {
		int lo = 0, hi = a.size()-1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			int x = a.get(mid);
			if(x > key) hi = mid-1;
			else if(x < key) lo = mid+1;
			else return true;
		}
		return false;
	}

	int find(Edge[] a, int color, boolean x) {
		int lo = 0, hi = a.length-1;
		int ret = -1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			if(a[mid].color > color) {
				hi = mid-1;
			}
			else if(a[mid].color < color) {
				lo = mid+1;
			}
			else {
				ret = mid;
				if(!x) hi = mid-1;
				else lo = mid+1;
			}
		}
		return ret;
	}

	class Edge implements Comparable<Edge> {
		int to, color, id;
		Edge(int t, int c, int i) {
			to = t;
			color = c;
			id = i;
		}
		public int compareTo(Edge e) {
			return Integer.compare(color, e.color);
		}
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


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

public class D implements Runnable {
	public static void main (String[] args) {new Thread(null, new D(), "_cf", 1 << 28).start();}

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt(), m = fs.nextInt();
		int[][] edges = new int[m][5];
		int[] deg = new int[n];
		for(int i = 0; i < m; i++) {
			for(int j = 0; j < 2; j++) {
				edges[i][j] = fs.nextInt()-1;
				deg[edges[i][j]]++;
			}
			edges[i][2] = fs.nextInt();
			edges[i][3] = i;
		}
		Edge[][] adj = new Edge[n][];
		for(int i = 0; i < n; i++) {
			adj[i] = new Edge[deg[i]];
			deg[i] = 0;
		}

		for(int i = 0; i < m; i++) {
			int u = edges[i][0], v = edges[i][1];
			int color = edges[i][2];
			adj[u][deg[u]] = new Edge(v, color, i);
			adj[v][deg[v]] = new Edge(u, color, i);
			deg[u]++; deg[v]++;
		}

		int q = fs.nextInt();
		int[][] queries = new int[q][3];
		for(int i = 0; i < q; i++) {
			for(int j = 0; j < 2; j++) {
				queries[i][j] = fs.nextInt()-1;
			}
			if(queries[i][0] < queries[i][1]) {
				int temp = queries[i][0];
				queries[i][0] = queries[i][1];
				queries[i][1] = temp;
			}
			queries[i][2] = i;
		}

		for(int i = 0; i < n; i++) {
			Arrays.sort(adj[i]);
		}
		Arrays.sort(edges, (a, b) -> Integer.compare(a[2], b[2]));

		for(int i = 0; i < m; i++) edges[i][4] = i;

		boolean[] used = new boolean[m];
		int[] queue = new int[m];
		int[] visTime = new int[n];
		int curColor = 1;
		ArrayList<Integer>[] allTimes = new ArrayList[n];
		for(int i = 0; i < n; allTimes[i++] = new ArrayList<>());
		HashMap<Integer, Integer>[] maps = new HashMap[n];
		for(int i = 0; i < n; i++) maps[i] = new HashMap<>();
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < adj[i].length; j++) {
				int col = adj[i][j].color;
				if(!maps[i].containsKey(col)) maps[i].put(col, j);
			}
		}

		for(int i = 0; i < edges.length; i++) {
			int upTo = i;
			while(upTo < edges.length && edges[i][2] == edges[upTo][2]) {
				upTo++;
			}
			for(int k = i; k < upTo; k++) {
				int id = edges[k][3];
				if(used[id]) continue;
				int tail = 0;
				queue[tail++] = edges[k][0];
				queue[tail++] = edges[k][1];
				visTime[edges[k][0]] = curColor;
				visTime[edges[k][1]] = curColor;
				used[id] = true;

				for(int j = 0; j < tail; j++) {
					int u = queue[j];
					allTimes[u].add(curColor);
					int startIdx = maps[u].get(edges[i][2]);
					for(int ii = startIdx; ii < adj[u].length; ii++) {
						if(adj[u][ii].color != edges[i][2]) break;
						int v = adj[u][ii].to;
						if(visTime[v] == curColor) continue;
						if(used[adj[u][ii].id]) continue;
						visTime[v] = curColor;
						queue[tail++] = v;
						used[adj[u][ii].id] = true;
					}
				}
				curColor++;
			}
			i = --upTo;
		}

		Arrays.sort(queries, (a, b) -> Integer.compare(a[0], b[0]) == 0 ? Integer.compare(a[1], b[1]) : Integer.compare(a[0], b[0]));

		for(int i = 0; i < n; i++) {
			maps[i].clear();
			for(int j : allTimes[i]) maps[i].put(j, 0);
		}
		int[] res = new int[q];
		for(int i = 0; i < q; i++) {
			int upTo = i;
			while(upTo < q && queries[i][0] == queries[upTo][0] && queries[i][1] == queries[upTo][1]) upTo++;
			int u = queries[i][0];
			int v = queries[i][1];
			if(adj[v].length < adj[u].length) {
				int temp = v;
				v = u; u = temp;
			}
			int ret = 0;
			for(int time : allTimes[u]) {
				if(maps[v].containsKey(time)) ret++;
			}
			for(int j = i; j < upTo; j++) res[queries[j][2]] = ret;
			i = --upTo;
		}
		for(int i : res) out.println(i);

		out.close();
	}

	boolean find(ArrayList<Integer> a, int key) {
		int lo = 0, hi = a.size()-1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			int x = a.get(mid);
			if(x > key) hi = mid-1;
			else if(x < key) lo = mid+1;
			else return true;
		}
		return false;
	}

	int find(Edge[] a, int color, boolean x) {
		int lo = 0, hi = a.length-1;
		int ret = -1;
		for(int bs = 0; bs < 50 && lo <= hi; bs++) {
			int mid = (lo+hi)/2;
			if(a[mid].color > color) {
				hi = mid-1;
			}
			else if(a[mid].color < color) {
				lo = mid+1;
			}
			else {
				ret = mid;
				if(!x) hi = mid-1;
				else lo = mid+1;
			}
		}
		return ret;
	}

	class Edge implements Comparable<Edge> {
		int to, color, id;
		Edge(int t, int c, int i) {
			to = t;
			color = c;
			id = i;
		}
		public int compareTo(Edge e) {
			return Integer.compare(color, e.color);
		}
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = 0;
    if (it == vertix[v].end())
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    else
    {
        ret = it->second;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (vb == va)
        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    if (a > b)
        swap(a,b);

    map<pair<int,int>, int >::iterator it = ans.find(make_pair(a,b));
    if (it != ans.end())
        return it->second;

    map<int,int> *x = &vertix[a];
    map<int,int> *y = &vertix[b];

    if (vertix[a].size() > vertix[b].size())
    {
        x = &vertix[b];
        y = &vertix[a];
    }

    int ret = 0;
    for(map<int,int>::iterator it = x->begin(); it != x->end(); ++it)
    {
        map<int,int>::iterator ity = y->find(it->first);
        if (ity != y->end())
        {
            if (get_root(ity->second) == get_root(it->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (vb == va)
        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    if (a > b)
        swap(a,b);

    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = &vertix[a];
    map<int,int> *y = &vertix[b];

//    if (vertix[a].size() > vertix[b].size())
//    {
//        x = &vertix[b];
//        y = &vertix[a];
//    }

    int ret = 0;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(ity->second) == get_root(itx->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
//    if (vb == va)
//        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = vertix + a;
    map<int,int> *y = vertix + b;

    if (vertix[a].size() > vertix[b].size())
    {
        x = vertix + b;
        y = vertix + a;
    }

    int ret = 0;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(itx->second) == get_root(ity->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        if (u > v)
            swap(u,v);
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (vb == va)
        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    if (a > b)
        swap(a,b);

    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = &vertix[a];
    map<int,int> *y = &vertix[b];

    if (vertix[a].size() > vertix[b].size())
    {
        x = &vertix[b];
        y = &vertix[a];
    }

    int ret = 0;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(ity->second) == get_root(itx->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (vb == va)
        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    if (a > b)
        swap(a,b);

    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = &vertix[a];
    map<int,int> *y = &vertix[b];

    if (vertix[a].size() > vertix[b].size())
    {
        x = &vertix[b];
        y = &vertix[a];
    }

    int ret = 0;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (itx->second == ity->second)
            {
                cout << "ERROR!" << endl;
            }
            if (get_root(itx->second) == get_root(ity->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (vb == va)
        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    if (a > b)
        swap(a,b);

    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = &vertix[a];
    map<int,int> *y = &vertix[b];

    if (vertix[a].size() > vertix[b].size())
    {
        x = &vertix[b];
        y = &vertix[a];
    }

    int ret = 0;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(itx->second) == get_root(ity->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    if (ret == 5038)
        cout << a << " " << b << endl;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (vb == va)
        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    if (a > b)
        swap(a,b);

    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = &vertix[a];
    map<int,int> *y = &vertix[b];

    if (vertix[a].size() > vertix[b].size())
    {
        x = &vertix[b];
        y = &vertix[a];
    }

    int ret = 0;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(itx->second) == get_root(ity->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    if (ret == 5038)
        cout << cnt_point << endl;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (vb == va)
        return;
    par[va] = vb;
//    if (rank[va] > rank[vb])
//        par[vb] = va;
//    if (rank[vb] > rank[va])
//        par[va] = vb;
//    if (rank[va] == rank[vb])
//    {
//        par[vb] = va;
//        ++rank[va];
//    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    if (a > b)
        swap(a,b);

    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = &vertix[a];
    map<int,int> *y = &vertix[b];

    if (vertix[a].size() > vertix[b].size())
    {
        x = &vertix[b];
        y = &vertix[a];
    }

    int ret = 0;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(itx->second) == get_root(ity->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
#include <vector>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

typedef pair<int,int> pii;

int const maxn = 100005;

map<int, int> vertix[maxn];

vector<pii> dsp;

int get_root(int a)
{
    int tmp = a;
    while (dsp[tmp].first != tmp)
        tmp = dsp[tmp].first;
    while (a != tmp)
    {
        int next = dsp[a].first;
        dsp[a].first = tmp;
        a = next;
    }
    return a;
}

void un(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (dsp[va].second < dsp[vb].second)
        dsp[vb].first = va;
    if (dsp[va].second > dsp[vb].second)
        dsp[va].first = vb;
    if (dsp[va].second == dsp[vb].second)
    {
        ++dsp[va].second;
        dsp[vb].first = va;
    }
}

map<pair<int,int>, int> ans;

int get_ans(int a, int b)
{
    map<pair<int,int>, int>::iterator it = ans.find(make_pair(a,b));
    if (it != ans.end())
        return it->second;

    map<int, int> *x = vertix+a;
    map<int, int> *y = vertix+b;
    if (x->size() > y->size())
        swap(x,y);

    int ret = 0;
    for(map<int, int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int, int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(ity->second) == get_root(itx->second))
            {
                ++ret;
            }
//            cerr << a << " " << b << " " << itx->first <<" " << ity->second<<" " << itx->second <<" "<<get_root(ity->second) << " " << get_root(itx->second) << endl;
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

int get_vertix(int v, int color)
{
    map<int, int>::iterator it = vertix[v].find(color);
    if (it != vertix[v].end())
    {
        return it->second;
    }
    else
    {
        int ret = dsp.size();
        dsp.push_back(make_pair(ret,0));
        vertix[v].insert(make_pair(color, ret) );
        return ret;
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_vertix(a,c);
    int vb = get_vertix(b,c);
    un(va,vb);
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

//    forn(i, maxn)
//        if(vertix[i].size() > 0)
//        {
//            cerr << "att " << i << endl;
//            for(map<int, int>::iterator itx = (vertix+i)->begin(); itx != (vertix+i)->end(); ++itx)
//                cerr << itx->first << " " << itx->second << endl;
//        }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        if (u > v)
            swap(u,v);
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
    if (vb == va)
        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    if (a > b)
        swap(a,b);

    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = &vertix[a];
    map<int,int> *y = &vertix[b];

    if (vertix[a].size() > vertix[b].size())
    {
        x = &vertix[b];
        y = &vertix[a];
    }

    int ret = 0;
    int last = -1;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        if (last == itx->first)
        {
            cout << "ERROR!" <<endl;
            return -1;
        }
        last = itx->first;
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(ity->second) == get_root(itx->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <map>
using namespace std;

#define forn(i,n) for(int i = 0; i < (int)(n); ++i)

int const maxn = 100005;

map<int,int> vertix[maxn];

int par[2*maxn];
int rank[2*maxn];
int cnt_point = 0;

int get_point(int v, int color)
{
    map<int,int>::iterator it = vertix[v].find(color);
    int ret = -1;
    if (it != vertix[v].end())
    {
        ret = it->second;
    }
    else
    {
        ret = cnt_point++;
        vertix[v][color] = ret;
    }
    return ret;
}

int get_root(int v)
{
    int cur = v;
    while (par[cur] != cur)
        cur = par[cur];
    while (v != cur)
    {
        int next = par[v];
        par[v] = cur;
        v = next;
    }
    return v;
}

void uni(int a, int b)
{
    int va = get_root(a);
    int vb = get_root(b);
//    if (vb == va)
//        return;
    if (rank[va] > rank[vb])
        par[vb] = va;
    if (rank[vb] > rank[va])
        par[va] = vb;
    if (rank[va] == rank[vb])
    {
        par[vb] = va;
        ++rank[va];
    }
}

void add_edge(int a, int b, int c)
{
    int va = get_point(a,c);
    int vb = get_point(b,c);
    uni(va,vb);
}

map<pair<int,int>, int > ans;

int get_ans(int a, int b)
{
    map<pair<int,int>, int >::iterator it_ans = ans.find(make_pair(a,b));
    if (it_ans != ans.end())
        return it_ans->second;

    map<int,int> *x = vertix + a;
    map<int,int> *y = vertix + b;

    if (vertix[a].size() > vertix[b].size())
    {
        x = vertix + b;
        y = vertix + a;
    }

    int ret = 0;
    for(map<int,int>::iterator itx = x->begin(); itx != x->end(); ++itx)
    {
        map<int,int>::iterator ity = y->find(itx->first);
        if (ity != y->end())
        {
            if (get_root(itx->second) == get_root(ity->second))
            {
                ++ret;
            }
        }
    }
    ans[make_pair(a,b)] = ret;
    return ret;
}

void init()
{
    forn(i,maxn)
        par[i] = i;
}

int main()
{
    ios_base::sync_with_stdio(false);
    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    cout << fixed << setprecision(10);
    init();
    int n,m;
    cin >> n >> m;
    forn(i,m)
    {
        int a,b,c;
        cin >> a >> b >> c;
        add_edge(a,b,c);
    }

    int q = 0;
    cin >> q;
    forn(i, q)
    {
        int u,v;
        cin >> u >> v;
        if (u > v)
            swap(u,v);
        cout << get_ans(u,v) << "\n";
    }

    return 0;
}


#include <cstdio>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <set>
#include <vector>

using namespace std;

const int buf_len = 3001;
const int buf_size = buf_len * sizeof(char);
char buf[buf_len], *bufb(buf + buf_len - 1), *bufe(buf + buf_len);
#define readBuf() { \
	if (++ bufb == bufe) { \
		bufe = buf + fread(buf, 1, buf_size, stdin); \
		bufb = buf; \
	} \
}
#define readInt(_x_) { \
	register int _s_(0); \
	do { \
		readBuf(); \
	} while (!isdigit(*bufb)); \
	do { \
		_s_ = (_s_ << 3) + (_s_ * 2) + *bufb - 48; \
		readBuf(); \
	} while (isdigit(*bufb)); \
	_x_ = _s_; \
}

typedef unsigned int uint;
typedef pair <int, int> qpr;
typedef set <int> :: iterator setiter;

struct qry {
	int a, b, s;
};
struct edge {
	int a, b, c;
};
inline bool cmpEdge(const edge& a, const edge& b) {
	return a. c < b. c;
}

const int maxn = 100009;
const int maxs = 309;
const int maxa = maxn * maxs;

int n, m, tq, t, r[maxn], rtm[maxn], ttm;
edge e[maxn];
qry q[maxn];
qpr a[maxa];
set <int> rp;
int p[maxn];

inline int vis(int x) {
	if (rtm[x] == ttm)
		return r[x];
	else
		return rtm[x] = ttm, r[x] = x;
}

inline void chg(int x, int v) {
	rtm[x] = ttm;
	r[x] = v;
}

int getRoot(int x) {
	int p, q;
	for (p = x; vis(p) ^ p; p = r[p]);
	for (; x ^ p; q = vis(x), chg(x, p), x = q);
	return p;
}

inline void join(int u, int v) {
	if (getRoot(u) ^ getRoot(v))
		chg(getRoot(u), getRoot(v));
}

int main() {
	readInt(n);
	readInt(m);
	for (int i = 0; i < m; ++ i) {
		readInt(e[i]. a);
		readInt(e[i]. b);
		readInt(e[i]. c);
		if (e[i]. a > e[i]. b)
			swap(e[i]. a, e[i]. b);
	}
	sort(e, e + m, cmpEdge);
	readInt(tq);
	for (int i = 0; i < tq; ++ i) {
		readInt(q[i]. a);
		readInt(q[i]. b);
		q[i]. s = 0;
	}
	memset(rtm, 0, sizeof(rtm));
	ttm = 0;
	t = 0;
	for (int i = 0, j; i < m; i = j) {
		for (j = i; j < m && e[j]. c == e[i]. c; ++ j);
		if (j - i > 100) {
			++ ttm;
			for (int k = i; k < j; ++ k)
				join(e[k]. a, e[k]. b);
			for (int k = 0; k < tq; ++ k)
				if (getRoot(q[k]. a) == getRoot(q[k]. b))
					++ q[i]. s;
		}
		else {
			++ ttm;
			rp. clear();
			for (int k = i; k < j; ++ k) {
				join(e[k]. a, e[k]. b);
				rp. insert(e[k]. a);
				rp. insert(e[k]. b);
			}
			uint e = 0;
			for (set <int> :: iterator it = rp. begin(); it != rp. end(); ++ it)
				p[e ++] = *it;
			for (uint i = 0; i < e; ++ i)
				for (uint j = i + 1; j < e; ++ j)
					if (getRoot(p[i]) == getRoot(p[j]))
						a[t ++] = qpr(p[i], p[j]);
		}
	}
	sort(a, a + t);
	for (int i = 0; i < tq; ++ i) {
		if (q[i]. a > q[i]. b)
			swap(q[i]. a, q[i]. b);
		qpr g(q[i]. a, q[i]. b);
		q[i]. s += upper_bound(a, a + t, g) - lower_bound(a, a + t, g);
		printf("%d\n", q[i]. s);
	}
}


#include <cstdio>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <set>
#include <vector>

using namespace std;

const int buf_len = 3001;
const int buf_size = buf_len * sizeof(char);
char buf[buf_len], *bufb(buf + buf_len - 1), *bufe(buf + buf_len);
#define readBuf() { \
	if (++ bufb == bufe) { \
		bufe = buf + fread(buf, 1, buf_size, stdin); \
		bufb = buf; \
	} \
}
#define readInt(_x_) { \
	register int _s_(0); \
	do { \
		readBuf(); \
	} while (!isdigit(*bufb)); \
	do { \
		_s_ = (_s_ << 3) + (_s_ * 2) + *bufb - 48; \
		readBuf(); \
	} while (isdigit(*bufb)); \
	_x_ = _s_; \
}

typedef unsigned int uint;
typedef pair <int, int> qpr;
typedef set <int> :: iterator setiter;

struct qry {
	int a, b, s;
};
struct edge {
	int a, b, c;
};
inline bool cmpEdge(const edge& a, const edge& b) {
	return a. c < b. c;
}

const int maxn = 100009;
const int maxs = 309;
const int maxa = maxn * maxs;

int n, m, tq, t, r[maxn], rtm[maxn], ttm;
edge e[maxn];
qry q[maxn];
qpr a[maxa];
set <int> rp;
int p[maxn];

inline int vis(int x) {
	if (rtm[x] == ttm)
		return r[x];
	else
		return rtm[x] = ttm, r[x] = x;
}

inline void chg(int x, int v) {
	rtm[x] = ttm;
	r[x] = v;
}

int getRoot(int x) {
	int p, q;
	for (p = x; vis(p) ^ p; p = r[p]);
	for (; x ^ p; x = q) {
		q = vis(x);
		chg(x, p);
	}
	return p;
}

inline void join(int u, int v) {
	if (getRoot(u) ^ getRoot(v))
		chg(getRoot(u), getRoot(v));
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	readInt(n);
	readInt(m);
	for (int i = 0; i < m; ++ i) {
		readInt(e[i]. a);
		readInt(e[i]. b);
		readInt(e[i]. c);
		if (e[i]. a > e[i]. b)
			swap(e[i]. a, e[i]. b);
	}
	sort(e, e + m, cmpEdge);
	readInt(tq);
	for (int i = 0; i < tq; ++ i) {
		readInt(q[i]. a);
		readInt(q[i]. b);
		q[i]. s = 0;
	}
	memset(rtm, 0, sizeof(rtm));
	ttm = 0;
	t = 0;
	for (int i = 0, j; i < m; i = j) {
		for (j = i; j < m && e[j]. c == e[i]. c; ++ j);
		if (j - i > 100) {
			++ ttm;
			for (int k = i; k < j; ++ k)
				join(e[k]. a, e[k]. b);
			for (int k = 0; k < tq; ++ k)
				if (getRoot(q[k]. a) == getRoot(q[k]. b))
					++ q[i]. s;
		}
		else {
			++ ttm;
			rp. clear();
			for (int k = i; k < j; ++ k) {
				join(e[k]. a, e[k]. b);
				rp. insert(e[k]. a);
				rp. insert(e[k]. b);
			}
			uint e = 0;
			for (set <int> :: iterator it = rp. begin(); it != rp. end(); ++ it)
				p[e ++] = *it;
			for (uint i = 0; i < e; ++ i)
				for (uint j = i + 1; j < e; ++ j)
					if (getRoot(p[i]) == getRoot(p[j]))
						a[t ++] = qpr(p[i], p[j]);
		}
	}
	sort(a, a + t);
	for (int i = 0; i < tq; ++ i) {
		if (q[i]. a > q[i]. b)
			swap(q[i]. a, q[i]. b);
		qpr g(q[i]. a, q[i]. b);
		q[i]. s += upper_bound(a, a + t, g) - lower_bound(a, a + t, g);
		printf("%d\n", q[i]. s);
	}
}