Ali is Hamed's little brother and tomorrow is his birthday. Hamed wants his brother to earn his gift so he gave him a hard programming problem and told him if he can successfully solve it, he'll get him a brand new laptop. Ali is not yet a very talented programmer like Hamed and although he usually doesn't cheat but this time is an exception. It's about a brand new laptop. So he decided to secretly seek help from you. Please solve this problem for Ali. 

An n-vertex weighted rooted tree is given. Vertex number 1 is a root of the tree. We define d(u, v) as the sum of edges weights on the shortest path between vertices u and v. Specifically we define d(u, u) = 0. Also let's define S(v) for each vertex v as a set containing all vertices u such that d(1, u) = d(1, v) + d(v, u). Function f(u, v) is then defined using the following formula:

<image>

The goal is to calculate f(u, v) for each of the q given pair of vertices. As the answer can be rather large it's enough to print it modulo 109 + 7.

Input

In the first line of input an integer n (1 ≤ n ≤ 105), number of vertices of the tree is given.

In each of the next n - 1 lines three space-separated integers ai, bi, ci (1 ≤ ai, bi ≤ n, 1 ≤ ci ≤ 109) are given indicating an edge between ai and bi with weight equal to ci.

In the next line an integer q (1 ≤ q ≤ 105), number of vertex pairs, is given.

In each of the next q lines two space-separated integers ui, vi (1 ≤ ui, vi ≤ n) are given meaning that you must calculate f(ui, vi).

It is guaranteed that the given edges form a tree.

Output

Output q lines. In the i-th line print the value of f(ui, vi) modulo 109 + 7.

Examples

Input

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


Output

10
1000000005
1000000002
23
1000000002


Input

8
1 2 100
1 3 20
2 4 2
2 5 1
3 6 1
3 7 2
6 8 5
6
1 8
2 3
5 8
2 6
4 7
6 1


Output

999968753
49796
999961271
999991235
999958569
45130
#include <bits/stdc++.h>
using namespace std;
inline int MODP(long long x) {
  int r = x % 1000000007;
  if (r < 0) r += 1000000007;
  return r;
}
void testGen() {
  freopen("biginput1.txt", "w", stdout);
  fclose(stdout);
}
int n;
struct weighted_tree {
  vector<vector<pair<int, int> > > adj;
  vector<pair<int, int> > pi;
  vector<int> depth;
  int n;
  int root;
  void reset(int n) {
    this->n = n;
    adj.resize(n + 1);
    for (auto i = 1; i <= n; ++i) adj[i].clear();
    pi.resize(n + 1);
    depth.resize(n + 1);
    for (auto i = 1; i <= n; ++i) {
      pi[i] = make_pair(-1, -1);
      depth[i] = 0;
    }
  }
  weighted_tree() {}
  weighted_tree(int n) { reset(n); }
  void dfs(int u) {
    for (auto &e : adj[u]) {
      int v = e.first;
      int c = e.second;
      if (pi[v].first == -1) {
        pi[v] = make_pair(u, c);
        depth[v] = depth[u] + 1;
        dfs(v);
      }
    }
  }
  void set_root(int u) {
    root = u;
    pi[root].first = -2;
    dfs(root);
  }
  void add_edge(int u, int v, int c) {
    adj[u].push_back(make_pair(v, c));
    adj[v].push_back(make_pair(u, c));
  }
};
struct lca {
  vector<vector<pair<int, int> > > anc;
  weighted_tree &t;
  lca(weighted_tree &tree) : t(tree) {
    anc.resize(t.n + 1);
    for (auto i = 1; i <= t.n; ++i) {
      if (i != t.root) {
        anc[i].push_back(t.pi[i]);
      }
    }
    for (int k = 1;; ++k) {
      bool ok = false;
      for (auto i = 1; i <= t.n; ++i) {
        if (anc[i].size() >= k) {
          int j = anc[i][k - 1].first;
          if (anc[j].size() >= k) {
            int x = anc[j][k - 1].first;
            int c = min(anc[i][k - 1].second, anc[j][k - 1].second);
            anc[i].push_back(make_pair(x, c));
            ok = true;
          }
        }
      }
      if (!ok) break;
    }
  }
  pair<int, int> get_lca(int u, int v) {
    if (t.depth[u] > t.depth[v]) {
      swap(u, v);
    }
    if (t.depth[v] > t.depth[u]) {
      for (auto i = anc[v].size() - 1; i >= 0; --i) {
        int w = anc[v][i].first;
        if (t.depth[w] >= t.depth[u]) {
          pair<int, int> p = get_lca(u, w);
          p.second = min(anc[v][i].second, p.second);
          return p;
        }
      }
    } else {
      if (u == v) {
        return make_pair(u, 2E9L);
      }
      for (auto i = anc[u].size() - 1; i >= 0; --i) {
        int x = anc[u][i].first;
        int y = anc[v][i].first;
        if (x != y || i == 0) {
          pair<int, int> p = get_lca(x, y);
          p.second = min(anc[u][i].second, p.second);
          p.second = min(anc[v][i].second, p.second);
          return p;
        }
      }
    }
    return make_pair(-1, -1);
  }
};
bool visit[100100];
weighted_tree tree;
int sumWeight[100100];
int cntNode[100100];
int sumDist[100100];
int sumSqrDist[100100];
int sumAllSqrDist[100100];
int sumAllDist[100100];
int getDistInc(int w, int v) {
  return MODP((long long)cntNode[v] * w + sumDist[v]);
}
int getSqrDistInc(int w, int v) {
  int sqrDistInc = MODP((long long)w * w);
  sqrDistInc = MODP((long long)sqrDistInc * cntNode[v]);
  sqrDistInc = MODP(sqrDistInc + (long long)2 * w * sumDist[v]);
  sqrDistInc = MODP(sqrDistInc + sumSqrDist[v]);
  return sqrDistInc;
}
void dfs(int u) {
  visit[u] = true;
  cntNode[u] = 1;
  sumDist[u] = 0;
  sumSqrDist[u] = 0;
  for (auto &e : tree.adj[u]) {
    int v = e.first, w = e.second;
    if (v != tree.pi[u].first && !visit[v]) {
      sumWeight[v] = MODP(sumWeight[u] + w);
      dfs(v);
      cntNode[u] += cntNode[v];
      sumDist[u] = MODP(sumDist[u] + getDistInc(w, v));
      sumSqrDist[u] = MODP(sumSqrDist[u] + getSqrDistInc(w, v));
    }
  }
}
void dfsSumAllDist(int u) {
  visit[u] = true;
  for (auto &e : tree.adj[u]) {
    int v = e.first, w = e.second;
    if (v != tree.pi[u].first && !visit[v]) {
      int nOutside = n - cntNode[v];
      int retSumDist = sumAllDist[u];
      retSumDist = MODP(retSumDist - getDistInc(w, v));
      int retSumSqrDist = sumAllSqrDist[u];
      retSumSqrDist = MODP(retSumSqrDist - getSqrDistInc(w, v));
      int inc = MODP((long long)w * w);
      inc = MODP((long long)inc * nOutside);
      inc = MODP(inc + (long long)2 * w * retSumDist);
      retSumSqrDist = MODP(retSumSqrDist + inc);
      retSumDist = MODP(retSumDist + (long long)w * nOutside);
      retSumDist = MODP(retSumDist + sumDist[v]);
      sumAllDist[v] = retSumDist;
      retSumSqrDist = MODP(retSumSqrDist + sumSqrDist[v]);
      sumAllSqrDist[v] = retSumSqrDist;
      dfsSumAllDist(v);
    }
  }
}
int main() {
  scanf("%d", &n);
  tree.reset(n);
  int a, b, c;
  for (auto repeat_var = 0; repeat_var < n - 1; ++repeat_var) {
    scanf("%d%d%d", &a, &b, &c);
    tree.add_edge(a, b, c);
  }
  tree.set_root(1);
  memset(visit, 0, sizeof(visit));
  sumWeight[1] = 0;
  dfs(1);
  memset(visit, 0, sizeof(visit));
  sumAllSqrDist[1] = sumSqrDist[1];
  sumAllDist[1] = sumDist[1];
  dfsSumAllDist(1);
  lca tree_lca(tree);
  int q;
  scanf("%d", &q);
  int u, v;
  for (auto repeat_var = 0; repeat_var < q; ++repeat_var) {
    scanf("%d%d", &u, &v);
    int ret;
    if (u == v) {
      ret = MODP(2 * sumSqrDist[u] - sumAllSqrDist[u]);
    } else {
      int x = tree_lca.get_lca(u, v).first;
      if (x == v) {
        int w = MODP(sumWeight[u] - sumWeight[v]);
        int nOutside = n - cntNode[v];
        ret = 0;
        ret = MODP(sumAllSqrDist[v] - sumSqrDist[v]);
        int retSumDist = MODP(sumAllDist[v] - sumDist[v]);
        int inc = MODP((long long)w * w);
        inc = MODP((long long)inc * nOutside);
        inc = MODP(inc + (long long)2 * w * retSumDist);
        ret = MODP(ret + inc);
        ret = MODP(sumAllSqrDist[u] - 2 * ret);
      } else {
        int w = MODP(sumWeight[u] - sumWeight[x]);
        w = MODP(w + sumWeight[v] - sumWeight[x]);
        int inc = MODP((long long)w * w);
        inc = MODP((long long)inc * cntNode[v]);
        inc = MODP(inc + (long long)2 * w * sumDist[v]);
        ret = MODP(sumSqrDist[v] + inc);
        ret = MODP(2 * ret - sumAllSqrDist[u]);
      }
    }
    cout << ret << endl;
  }
  return 0;
}
