#include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

class Edge
{
public:
    int to, cost;
    Edge(){};
    Edge(int to0, int cost0){to = to0; cost = cost0;}
};

void shortestPath(const vector<vector<Edge> >& edges, int start, vector<long long>& dist)
{
    dist.assign(edges.size(), LLONG_MAX);
    dist[start] = 0;
    priority_queue<pair<long long,int> ,vector<pair<long long,int> >, greater<pair<long long,int> > > q;
    q.push(make_pair(0, start));

    while(!q.empty()){
        pair<long long, int> p = q.top();
        q.pop();
        int v = p.second;
        if(dist[v] < p.first)
            continue;
        for(unsigned i=0; i<edges[v].size(); ++i){
            Edge e = edges[v][i];
            if(dist[v] + e.cost < dist[e.to]){
                dist[e.to] = dist[v] + e.cost;
                q.push(make_pair(dist[e.to], e.to));
            }
        }
    }
}

class BIT
{
    int n;
    vector<int> data;
public:
    BIT(int n){ // コンストラクタ
        this->n = n;
        data.assign(n+1, 0);
    }
    void add(int k, int x){ // k番目の要素にxを加算する
        ++ k;
        while(k <= n){
            data[k] += x;
            k += k & -k;
        }
    }
    int sum(int k){ // 区間[0,k]の総和を返す
        ++ k;
        int ret = 0;
        while(k > 0){
            ret += data[k];
            k -= k & -k;
        }
        return ret;
    }
    int sum(int a, int b){ // 区間[a,b]の総和を返す
        return sum(b) - sum(a-1);
    }
    int upper_bound(int x){ // 総和が初めてxを超える位置を返す（ただし、各位置の数値が非負数であることを前提とする）
        int b = 1;
        while(b < n)
            b *= 2;
        int a = 0;
        while(b > 0){
            if(a+b <= n && x >= data[a+b]){
                x -= data[a+b];
                a += b;
            }
            b /= 2;
        }
        return (a < n)? a : -1;
    }
    int lower_bound(int x){ // 総和が初めてx以上になる位置を返す（ただし、各位置の数値が非負数であることを前提とする）
        return upper_bound(x-1);
    }
};

class Data
{
public:
    long long fs, fg;
    int index;
    bool operator<(const Data& d) const{
        return fs < d.fs;
    }
};

int main()
{
    int n, m;
    cin >> n >> m;
    vector<vector<Edge> > edges(n);
    for(int i=0; i<m; ++i){
        int a, b, c;
        cin >> a >> b >> c;
        edges[a].push_back(Edge(b, c));
        edges[b].push_back(Edge(a, c));
    }

    int q;
    cin >> q;
    vector<Data> d(q);
    for(int i=0; i<q; ++i){
        cin >> d[i].fs >> d[i].fg;
        d[i].index = i;
    }
    sort(d.begin(), d.end());

    // クエリをfsの小さい順にソート
    vector<pair<long long, int> > fg(q);
    for(int i=0; i<q; ++i)
        fg[i] = make_pair(d[i].fg, i+1);
    fg.push_back(make_pair(LLONG_MIN, 0));
    fg.push_back(make_pair(LLONG_MAX, q+1));
    sort(fg.begin(), fg.end());

    vector<long long> distS0, distG;
    shortestPath(edges, 0, distS0);
    shortestPath(edges, n-1, distG);

    vector<pair<long long, int> > distS(n);
    for(int i=0; i<n; ++i)
        distS[i] = make_pair(distS0[i], i);
    sort(distS.begin(), distS.end());

    vector<int> ret(q);
    BIT b(q+2);
    int k = 0;
    for(int i=0; i<q; ++i){
        while(k < n && distS[k].first <= d[i].fs){
            int x = upper_bound(fg.begin(), fg.end(), make_pair(distG[distS[k].second], INT_MAX)) - fg.begin() - 1;
            b.add(x, 1);
            ++ k;
        }

        int x = lower_bound(fg.begin(), fg.end(), make_pair(d[i].fg, -1)) - fg.begin();
        ret[d[i].index] = b.sum(x, q);
    }

    for(int i=0; i<q; ++i)
        cout << ret[i] << endl;

    return 0;
}

Measured memory_bytes: 15952