#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, logN = 17, mod = 1e9 + 7;
inline int add(int x, int y) {
  x += y;
  if (x >= mod) x -= mod;
  return x;
}
inline int sub(int x, int y) {
  x -= y;
  if (x < 0) x += mod;
  return x;
}
inline int mul(int x, int y) { return (x * 1ll * y) % mod; }
inline int powr(int a, long long b) {
  int x = 1 % mod;
  while (b) {
    if (b & 1) x = mul(x, a);
    a = mul(a, a);
    b >>= 1;
  }
  return x;
}
inline int inv(int a) { return powr(a, mod - 2); }
int tree[N], vis[N], parcen[N];
vector<int> concen[N], con[N];
int par[logN][N], depth[N], prod[logN][N], black[logN][N];
vector<pair<int, int> > con2[N];
void dfs(int s, int d, int p) {
  depth[s] = d;
  par[0][s] = p;
  for (int i = 0; i < con[s].size(); i++) {
    int v = con[s][i];
    if (v != p) {
      dfs(v, d + 1, s);
      prod[0][v] = con2[s][i].first;
      black[0][v] = con2[s][i].second;
    }
  }
}
void pre(int n) {
  for (int j = 1; j < logN; j++)
    for (int i = 1; i <= n; i++) {
      int parent = par[j - 1][i];
      par[j][i] = par[j - 1][parent];
      prod[j][i] = mul(prod[j - 1][i], prod[j - 1][parent]);
      black[j][i] = black[j - 1][i] + black[j - 1][parent];
    }
}
int getSizes(int s, int p) {
  tree[s] = 1;
  for (int v : con[s])
    if (v != p && !vis[v]) tree[s] += getSizes(v, s);
  return tree[s];
}
int getcentroid(int s, int p, int n) {
  for (int v : con[s]) {
    if (v != p && !vis[v]) {
      if (2 * tree[v] > n) return getcentroid(v, s, n);
    }
  }
  return s;
}
int decompose(int s, int p) {
  int root = getcentroid(s, p, getSizes(s, p));
  parcen[root] = p;
  if (p > 0) concen[p].push_back(root), concen[root].push_back(p);
  vis[root] = 1;
  for (int v : con[root]) {
    if (!vis[v]) decompose(v, root);
  }
  return root;
}
inline pair<int, pair<int, int> > get(int a, int b) {
  int P = 1, B = 0, L = 0;
  if (depth[a] < depth[b]) swap(a, b);
  int l = depth[a] - depth[b];
  for (int i = 0; i < logN; i++) {
    if (l & (1 << i)) {
      P = mul(P, prod[i][a]);
      B += black[i][a];
      a = par[i][a];
    }
  }
  if (a == b) return {a, {P, B}};
  for (int i = logN - 1; i >= 0; i--) {
    if (par[i][a] != par[i][b]) {
      P = mul(P, mul(prod[i][a], prod[i][b]));
      B += black[i][a] + black[i][b];
      a = par[i][a];
      b = par[i][b];
    }
  }
  return {par[0][a],
          {mul(P, mul(prod[0][b], prod[0][a])), B + black[0][a] + black[0][b]}};
}
const int M = 1.3e7 + 10;
const int offset = 2 * N;
int lft[M], rgt[M], product[M], sz[M], cnt = 0;
void PRE() {
  for (int i = 0; i < M; i++) product[i] = 1;
}
struct segtree {
  int root;
  segtree() { root = ++cnt; }
  void ins(int rt, int x, int y, int s = 0, int e = 2 * offset) {
    sz[rt]++;
    product[rt] = mul(product[rt], y);
    if (s == e) return;
    int mid = (s + e) >> 1;
    if (x <= mid) {
      if (lft[rt] == 0) lft[rt] = ++cnt;
      ins(lft[rt], x, y, s, mid);
    } else {
      if (!rgt[rt]) rgt[rt] = ++cnt;
      ins(rgt[rt], x, y, mid + 1, e);
    }
  }
  void insert(int x, int y) {
    if (x <= -offset && x >= offset) return;
    ins(root, x + offset, y);
  }
  pair<int, int> get(int rt, int l, int r, int s = 0, int e = 2 * offset) {
    if (!rt) return {1, 0};
    if (r < s || l > e || r < l) return {1, 0};
    if (s >= l && e <= r) return {product[rt], sz[rt]};
    int mid = (s + e) >> 1;
    pair<int, int> P = get(lft[rt], l, r, s, mid);
    pair<int, int> Q = get(rgt[rt], l, r, mid + 1, e);
    return {mul(P.first, Q.first), P.second + Q.second};
  }
  pair<int, int> get(int x) {
    if (x <= -offset && x >= offset) return {0, 0};
    return get(root, 0, x + offset);
  }
};
segtree T[2][N];
vector<pair<int, pair<int, int> > > vvec;
int FREQ[N + 10], FREQ1[N + 10];
int main() {
  srand(time(NULL));
  PRE();
  for (int i = 0; i < N; i++) FREQ[i] = FREQ1[i] = 1;
  int n, u, v, x, c;
  scanf("%d", &(n));
  for (int i = 1; i < n; i++) {
    scanf("%d", &(u)), scanf("%d", &(v));
    scanf("%d", &(x));
    scanf("%d", &(c));
    con[u].push_back(v);
    con[v].push_back(u);
    con2[u].push_back({x, c});
    con2[v].push_back({x, c});
  }
  dfs(1, 0, 0);
  pre(n);
  int centroid = decompose(1, 0);
  int ans = 1;
  int _inv = 1;
  for (int i = 1; i <= n; i++) {
    int node = i;
    int prevnode = 0;
    vvec.clear();
    while (node) {
      pair<int, pair<int, int> > v = get(i, node);
      vvec.push_back(v);
      int x1 = v.second.second,
          y1 = depth[i] + depth[node] - 2 * depth[v.first] - x1;
      int P = v.second.first;
      pair<int, int> Q1 = T[0][node].get(2 * y1 - x1);
      pair<int, int> Q2 = T[1][prevnode].get(2 * y1 - x1);
      _inv = mul(_inv, Q2.first);
      int Prod = Q1.first;
      int freq = Q1.second - Q2.second;
      assert(freq >= 0);
      FREQ[freq] = mul(FREQ[freq], P);
      ans = mul(ans, Prod);
      prevnode = node;
      node = parcen[node];
    }
    node = i;
    prevnode = 0;
    int cntr = 0;
    while (node) {
      pair<int, pair<int, int> > v = vvec[cntr++];
      int x1 = v.second.second,
          y1 = depth[i] + depth[node] - 2 * depth[v.first] - x1;
      int P = v.second.first;
      T[0][node].insert(x1 - 2 * y1, P);
      if (prevnode) {
        T[1][prevnode].insert(x1 - 2 * y1, P);
      }
      prevnode = node;
      node = parcen[node];
    }
  }
  cnt = 1e6;
  memset(sz, 0, sizeof sz);
  memset(lft, 0, sizeof lft);
  memset(rgt, 0, sizeof rgt);
  for (int i = 0; i < M; i++) product[i] = 1;
  for (int i = 1; i <= n; i++) {
    int node = i;
    int prevnode = 0;
    vvec.clear();
    while (node) {
      pair<int, pair<int, int> > v = get(i, node);
      vvec.push_back(v);
      int x1 = v.second.second,
          y1 = depth[i] + depth[node] - 2 * depth[v.first] - x1;
      int P = v.second.first;
      pair<int, int> Q3 = T[0][node].get(y1 - 2 * x1 - 1);
      pair<int, int> Q4 = T[1][prevnode].get(y1 - 2 * x1 - 1);
      _inv = mul(_inv, Q3.first);
      int Prod = Q4.first;
      int freq = Q3.second - Q4.second;
      assert(freq >= 0);
      FREQ1[freq] = mul(FREQ1[freq], P);
      ans = mul(ans, Prod);
      prevnode = node;
      node = parcen[node];
    }
    node = i;
    prevnode = 0;
    int cntr = 0;
    while (node) {
      pair<int, pair<int, int> > v = vvec[cntr++];
      int x1 = v.second.second,
          y1 = depth[i] + depth[node] - 2 * depth[v.first] - x1;
      int P = v.second.first;
      T[0][node].insert(2 * x1 - y1, P);
      if (prevnode) {
        T[1][prevnode].insert(2 * x1 - y1, P);
      }
      prevnode = node;
      node = parcen[node];
    }
  }
  for (int i = 0; i < N; i++) {
    ans = mul(ans, powr(FREQ[i], i));
    ans = mul(ans, powr(inv(FREQ1[i]), i));
  }
  printf("%d\n", mul(ans, inv(_inv)));
}
