#include <bits/stdc++.h>
using namespace std;
const int Mod = 1000000007;
inline int fpow(int a, int b) {
  int ans = 1, t = a;
  while (b) {
    if (b & 1) ans = 1ll * ans * t % Mod;
    t = 1ll * t * t % Mod;
    b >>= 1;
  }
  return ans;
}
struct BIT {
  int n;
  int c[200010];
  inline int lowbit(int x) { return x & (-x); }
  inline void init(int N) {
    n = N;
    for (int i = 1; i <= n; i++) c[i] = 0;
    return;
  }
  inline void add(int x) {
    for (; x <= n; x += lowbit(x)) c[x]++;
    return;
  }
  inline int query(int x) {
    int ans = 0;
    for (; x; x -= lowbit(x)) ans += c[x];
    return ans;
  }
} S;
struct Val {
  int x, y;
  int val;
  Val() {}
  Val(int a, int b, int c) {
    x = a;
    y = b;
    val = c;
  }
} A[100010], B[100010];
int N1, N2;
int tmp[200010];
bool cmp(Val a, Val b) { return a.x < b.x; }
int solve() {
  int ans = 1, N = 0;
  for (int i = 1; i <= N1; i++) tmp[++N] = A[i].y;
  for (int i = 1; i <= N2; i++) tmp[++N] = B[i].y;
  S.init(N);
  sort(tmp + 1, tmp + N + 1);
  sort(A + 1, A + N1 + 1, cmp);
  sort(B + 1, B + N2 + 1, cmp);
  int now = 1;
  for (int i = 1; i <= N2; i++) {
    while (now <= N1 && A[now].x <= B[i].x) {
      S.add(lower_bound(tmp + 1, tmp + N + 1, A[now].y) - tmp);
      now++;
    }
    int tim = S.query(lower_bound(tmp + 1, tmp + N + 1, B[i].y) - tmp);
    ans = 1ll * ans * fpow(B[i].val, tim) % Mod;
  }
  return ans;
}
bool book[100010];
struct Edge {
  int v, c, kind, nxt;
} e[200010];
int tot;
int first[100010];
void build(int u, int v, int c, int kind) {
  e[++tot] = (Edge){v, c, kind, first[u]};
  first[u] = tot;
  return;
}
void getval(int u, int lst, int r, int b, int x) {
  A[++N1] = Val(r - 2 * b, b - 2 * r, 0);
  B[++N2] = Val(2 * b - r, 2 * r - b, x);
  for (int i = first[u]; i; i = e[i].nxt) {
    int v = e[i].v;
    int c = e[i].c;
    int kind = e[i].kind;
    if (book[v] || v == lst) continue;
    getval(v, u, r + (kind ^ 1), b + kind, 1ll * x * c % Mod);
  }
  return;
}
int calc(int u, int r = 0, int b = 0, int x = 1) {
  N1 = N2 = 0;
  getval(u, 0, r, b, x);
  return solve();
}
int siz[100010];
void getsiz(int u, int lst) {
  siz[u] = 1;
  for (int i = first[u]; i; i = e[i].nxt)
    if (e[i].v != lst && !book[e[i].v]) {
      getsiz(e[i].v, u);
      siz[u] += siz[e[i].v];
    }
  return;
}
void getmn(int u, int lst, int S, int& rt, int& mn) {
  int mx = S - siz[u];
  for (int i = first[u]; i; i = e[i].nxt)
    if (e[i].v != lst && !book[e[i].v]) {
      getmn(e[i].v, u, S, rt, mn);
      mx = max(mx, siz[e[i].v]);
    }
  if (mx < mn) {
    mn = mx;
    rt = u;
  }
  return;
}
int getroot(int u) {
  getsiz(u, 0);
  int rt = 0, mn = 1e9;
  getmn(u, 0, siz[u], rt, mn);
  return rt;
}
int final_ans = 1;
void divide(int u) {
  final_ans = 1ll * final_ans * calc(u) % Mod;
  book[u] = true;
  for (int i = first[u]; i; i = e[i].nxt) {
    int v = e[i].v;
    int c = e[i].c;
    int kind = e[i].kind;
    if (book[v]) continue;
    int res = calc(v, kind ^ 1, kind, c);
    final_ans = 1ll * final_ans * fpow(res, Mod - 2) % Mod;
  }
  for (int i = first[u]; i; i = e[i].nxt) {
    int v = e[i].v;
    if (book[v]) continue;
    int rt = getroot(v);
    divide(rt);
  }
  return;
}
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int u, v, c, kind;
    scanf("%d %d %d %d", &u, &v, &c, &kind);
    build(u, v, c, kind);
    build(v, u, c, kind);
  }
  int rt = getroot(1);
  divide(rt);
  printf("%d\n", final_ans);
  return 0;
}
