import std.stdio;
import std.ascii;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.random;
import std.regex;
import std.typecons;

const INF = long.max / 4;

int N, M, Q;

struct Edge {
    int from, to;
    long cost;
}

Edge[][] G;

long[] dijkstra(int v) {
    struct State {
        int v; long cost;
    }
    BinaryHeap!(Array!State, "a.cost > b.cost") PQ;
    PQ.insert(State(v, 0));
    auto d = new long[N];
    d[] = INF;
    d[v] = 0;
    while (!PQ.empty) {
        auto s = PQ.front; PQ.removeFront;
        foreach (e; G[s.v]) {
            if (d[e.to] <= s.cost + e.cost) continue;
            d[e.to] = s.cost + e.cost;
            PQ.insert(State(e.to, d[e.to]));
        }
    }
    return d;
}

struct Point {
    long x, y;
}

class Node {
    Node parent;
    Node left, right;
    long left_x, right_x;
    long[] ys;
    override string toString() const {
        return format("%s -> ys: %s", [left_x, right_x], ys);
    }
}
Node construct(in Point[] ps) {
    auto n = new Node;
    n.left_x = ps.front.x;
    n.right_x = ps.back.x;
    if (ps.length == 1) {
        n.ys = [ ps[0].y ];
        return n;
    }
    Node l = construct(ps[0 .. $ / 2]),
         r = construct(ps[$ / 2 .. $]);
    l.parent = n;
    r.parent = n;
    n.left = l;
    n.right = r;
    size_t li = 0, ri = 0;
    long[] ys;
    while (true) {
        if (li >= l.ys.length && ri >= r.ys.length) break;
        if (li >= l.ys.length) ys ~= r.ys[ri++];
        else if (ri >= r.ys.length) ys ~= l.ys[li++];
        else {
            ys ~= (l.ys[li] < r.ys[ri] ? l.ys[li++] : r.ys[ri++]);
        }
    }
    n.ys = ys;
    return n;
}
/* (sx <= x <= gx && sy <= y <= gy)なる点(x, y)の個数を返す */
long query(Node root, long sx, long gx, long sy, long gy) {
    if (gx < root.left_x || root.right_x < sx) {
        return 0;
    } else if (sx <= root.left_x && root.right_x <= gx) {
        auto ys = assumeSorted(root.ys);
        return ys.upperBound(sy - 1).lowerBound(gy + 1).length;
    } else {
        return query(root.left, sx, gx, sy, gy) + query(root.right, sx, gx, sy, gy);
    }
}

void main() {
    scanf("%d %d\n", &N, &M);
    G = new Edge[][N];
    foreach (i; 0 .. M) {
        int a, b, c;
        scanf("%d %d %d\n", &a, &b, &c);
        G[a] ~= Edge(a, b, c);
        G[b] ~= Edge(b, a, c);
    }
    auto ds = dijkstra(0),     // distance from start
         dg = dijkstra(N - 1); // distance from goal
    auto ps = new Point[N];
    foreach (i; 0 .. N) {
        ps[i].x = ds[i];
        ps[i].y = dg[i];
    }
    ps.sort!"a.x < b.x";
    Node segtree = construct(ps);
    /*
    void dump(Node t, int level = 0) {
        if (t is null) return;
        writeln(t);
        dump(t.left);
        dump(t.right);
    }
    dump(segtree);
    */
    scanf("%d\n", &Q);
    foreach (i; 0 .. Q) {
        long fs, fg;
        scanf("%lld %lld\n", &fs, &fg);
        writeln(query(segtree, 0, fs, fg, INF));
    }
}