#include <bits/stdc++.h>
using namespace std;
void Freopen() {
  freopen(
      "CF833D Red-Black Cobweb"
      ".in",
      "r", stdin);
  freopen(
      "CF833D Red-Black Cobweb"
      ".out",
      "w", stdout);
}
int read() {
  int g = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || '9' < ch) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while ('0' <= ch && ch <= '9') {
    g = g * 10 + ch - '0';
    ch = getchar();
  }
  return g * f;
}
const int N = 1e5 + 5;
const int INF = 1e9;
const int mod = 1e9 + 7;
int size[N], vis[N], n, w[N], op[N], mn, rt, top, T, ans = 1;
vector<pair<int, int> > G[N];
struct node {
  int A, B, w;
} st[N];
void getroot(int x, int fa, int S) {
  int mx = 0;
  size[x] = 1;
  for (auto y : G[x])
    if (y.first ^ fa)
      if (!vis[y.first]) {
        getroot(y.first, x, S);
        size[x] += size[y.first];
        mx = max(mx, size[y.first]);
      }
  mx = max(mx, S - size[x]);
  if (mx < mn) mn = mx, rt = x;
}
void dfs(int x, int fa, int d1, int d2, int wi) {
  st[++top] = node{2 * d1 - d2, 2 * d2 - d1, wi};
  for (auto y : G[x])
    if (y.first ^ fa)
      if (!vis[y.first])
        dfs(y.first, x, d1 + (op[y.second] == 0), d2 + (op[y.second] == 1),
            1ll * wi * w[y.second] % mod);
}
int ksm(int x, int y) {
  int re = 1;
  for (; y; y >>= 1, x = 1ll * x * x % mod)
    if (y & 1) re = 1ll * re * x % mod;
  return re;
}
struct Bit {
  int tag[N << 2], size[N << 2], t[N << 2];
  void insert(int x, int y) {
    x += 2 * n;
    for (; x <= 4 * n; x += x & -x) {
      if (tag[x] != T) size[x] = 0, t[x] = 1;
      size[x]++, t[x] = 1ll * t[x] * y % mod, tag[x] = T;
    }
  }
  void query(int x, int &w1, int &w2) {
    w1 = 1, w2 = 0, x += n * 2;
    for (; x; x -= x & -x) {
      if (tag[x] != T) continue;
      w1 = 1ll * w1 * t[x] % mod, w2 += size[x];
    }
  }
} bit1, bit2;
void getans(int x) {
  T++;
  bit1.insert(0, 1), bit2.insert(0, 1);
  for (auto y : G[x])
    if (!vis[y.first]) {
      top = 0;
      dfs(y.first, x, (op[y.second] == 0), (op[y.second] == 1), w[y.second]);
      for (int i = (1); i <= (top); i++) {
        int w1, w2;
        bit1.query(st[i].A, w1, w2);
        ans = 1ll * ans * w1 % mod * ksm(st[i].w, w2) % mod;
        bit2.query(-st[i].B - 1, w1, w2);
        ans = 1ll * ans * ksm(1ll * w1 * ksm(st[i].w, w2) % mod, mod - 2) % mod;
      }
      for (int i = (1); i <= (top); i++) {
        bit1.insert(-st[i].A, st[i].w);
        bit2.insert(st[i].B, st[i].w);
      }
    }
}
void getsize(int x, int fa) {
  size[x] = 1;
  for (auto y : G[x])
    if (y.first ^ fa)
      if (!vis[y.first]) {
        getsize(y.first, x);
        size[x] += size[y.first];
      }
}
void solve(int x, int S) {
  mn = INF, rt = 0;
  getroot(x, 0, S);
  x = rt;
  vis[x] = 1;
  getans(x);
  getsize(x, 0);
  for (auto y : G[x])
    if (!vis[y.first]) solve(y.first, size[y.first]);
}
signed main() {
  n = read();
  for (int i = (1); i <= (n - 1); i++) {
    int x = read(), y = read();
    G[x].push_back(pair<int, int>(y, i)), G[y].push_back(pair<int, int>(x, i));
    w[i] = read(), op[i] = read();
  }
  solve(1, n);
  cout << ans;
  return signed();
}
