#include <bits/stdc++.h>
using namespace std;
const int N = 110000, mod = 1e9 + 7;
int qpow(int x, int y) {
  int res = 1;
  while (y) {
    if (y & 1) res = 1ll * res * x % mod;
    x = 1ll * x * x % mod, y >>= 1;
  }
  return res;
}
int n, ans, head[N], ce;
int arr[N << 1];
struct edge {
  int to, nxt, w, c;
} e[N << 1];
void lnk(int a, int b, int w, int c) {
  e[++ce] = (edge){b, head[a], w, c}, head[a] = ce;
}
void mdf(int x, int s) {
  x += n;
  while (x <= n + n) arr[x] += s, x += (x & (-x));
}
int qry(int x) {
  x += n;
  int res = 0;
  while (x) res += arr[x], x -= (x & (-x));
  return res;
}
namespace Divide {
int tot, mn, rt, cnt, sz[N], used[N];
struct data {
  int x, y, w;
  bool operator<(const data& rhs) const { return x < rhs.x; }
} p[N], q[N];
void getRoot(int u, int lst) {
  sz[u] = 1;
  int mx = 0;
  for (int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].to;
    if (used[v] || v == lst) continue;
    getRoot(v, u);
    sz[u] += sz[v];
    mx = max(mx, sz[v]);
  }
  mx = max(mx, tot - sz[u]);
  if (mn > mx) mn = mx, rt = u;
}
void getDep(int u, int lst, int c0, int c1, int w) {
  p[++cnt] = (data){c0 - 2 * c1, c1 - 2 * c0, w};
  for (int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].to;
    if (used[v] || v == lst) continue;
    getDep(v, u, c0 + (e[i].c == 0), c1 + (e[i].c == 1),
           1ll * w * e[i].w % mod);
  }
}
void calc(int u, int c0, int c1, int w, int o) {
  cnt = 0;
  getDep(u, 0, c0, c1, w);
  sort(p + 1, p + cnt + 1);
  for (int i = 1; i <= cnt; ++i)
    q[i].x = -p[i].x, q[i].y = -p[i].y, q[i].w = p[i].w;
  reverse(q + 1, q + cnt + 1);
  int res = 1;
  for (int i = 1, j = 1; i <= cnt; ++i) {
    while (p[j].x <= q[i].x && j <= cnt) mdf(p[j++].y, 1);
    res = 1ll * res * qpow(q[i].w, qry(q[i].y) - (q[i].x >= 0 && q[i].y >= 0)) %
          mod;
  }
  for (int i = 1; p[i].x <= q[cnt].x && i <= cnt; ++i) mdf(p[i].y, -1);
  if (o == 1)
    ans = 1ll * ans * res % mod;
  else
    ans = 1ll * ans * qpow(res, mod - 2) % mod;
}
void dfs(int u) {
  used[u] = 1;
  calc(u, 0, 0, 1, 1);
  for (int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].to;
    if (used[v]) continue;
    calc(v, e[i].c == 0, e[i].c == 1, e[i].w, -1);
    tot = mn = sz[v], rt = 0;
    getRoot(v, 0), dfs(rt);
  }
}
void main() {
  tot = mn = n, rt = 0;
  getRoot(1, 0), dfs(rt);
}
}  // namespace Divide
int main() {
  scanf("%d", &n);
  for (int i = 1; i < n; ++i) {
    int x, y, w, c;
    scanf("%d%d%d%d", &x, &y, &w, &c);
    lnk(x, y, w, c), lnk(y, x, w, c);
  }
  ans = 1;
  Divide::main();
  printf("%d\n", ans);
  return 0;
}
