#include <bits/stdc++.h>
using namespace std;
inline void read(int &x) {
  x = 0;
  char c = getchar();
  while (c < '0' || c > '9') c = getchar();
  while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - 48, c = getchar();
}
const int maxn = 1e5 + 6, mod = 1e9 + 7, mx = 4e5 + 5;
int ans, n, M, Ms, rt, tot, first[maxn], sz[maxn], yet[maxn];
struct P {
  int A, B, W;
} T[maxn];
struct Road {
  int op, u, t, w, nxt;
} eage[maxn << 1];
void ad(int x, int y, int z, int w) {
  eage[++tot] = (Road){x, y, z, w, first[y]};
  first[y] = tot;
}
inline void inc(int &x, int y) {
  x += y;
  if (x >= mod) x -= mod;
}
inline void dec(int &x, int y) {
  x -= y;
  if (x < 0) x += mod;
}
inline int add(int x, int y) { return x + y >= mod ? x + y - mod : x + y; }
inline int dic(int x, int y) { return x - y < 0 ? x - y + mod : x - y; }
inline int mul(int x, int y) { return 1LL * x * y % mod; }
inline int qw(int a, int b, int ans = 1) {
  for (; b; b >>= 1, a = mul(a, a))
    if (b & 1) ans = mul(ans, a);
  return ans;
}
struct mr {
  int fr, se;
};
mr mp(int a, int b) { return (mr){a, b}; }
mr merge(mr a, mr b) { return mp(mul(a.fr, b.fr), a.se + b.se); }
struct BIT {
  mr c[maxn << 2];
  int lowbit(int x) { return x & (-x); }
  void init() {
    for (int i = 0; i <= mx; ++i) c[i] = mp(1, 0);
  }
  void Upd(int p, mr d) {
    for (p += maxn - 5 << 1; p <= mx; p += lowbit(p)) c[p] = merge(c[p], d);
  }
  mr Qry(int p, mr ans = mp(1, 0)) {
    for (p += maxn - 5 << 1; p; p -= lowbit(p)) ans = merge(ans, c[p]);
    return ans;
  }
} b1, b2;
void grdfs(int x, int fa) {
  sz[x] = 1;
  int mxp = 0;
  for (int i = first[x]; i; i = eage[i].nxt)
    if (eage[i].t != fa && !yet[eage[i].t])
      grdfs(eage[i].t, x), sz[x] += sz[eage[i].t],
          mxp = max(mxp, sz[eage[i].t]);
  mxp = max(mxp, M - sz[x]);
  if (mxp < Ms) rt = x, Ms = mxp;
}
void cldfs(int x, int fa, int a, int b, int w) {
  T[++tot] = (P){a, b, w};
  for (int i = first[x]; i; i = eage[i].nxt)
    if (eage[i].t != fa && !yet[eage[i].t])
      cldfs(eage[i].t, x, a + (eage[i].op == 0), b + (eage[i].op == 1),
            mul(w, eage[i].w));
}
void cal(int x) {
  int res = 1;
  b1.Upd(0, mp(1, 1)), b2.Upd(0, mp(1, 1));
  for (int i = first[x]; i; i = eage[i].nxt)
    if (!yet[eage[i].t]) {
      tot = 0, cldfs(eage[i].t, 0, eage[i].op == 0, eage[i].op == 1, eage[i].w);
      for (int j = 1; j <= tot; ++j) {
        mr F = b1.Qry(2 * T[j].A - T[j].B);
        res = mul(res, mul(F.fr, qw(T[j].W, F.se)));
        F = b2.Qry(T[j].A - 2 * T[j].B - 1);
        res = mul(res, qw(mul(F.fr, qw(T[j].W, F.se)), mod - 2));
      }
      for (int j = 1; j <= tot; ++j)
        b1.Upd(T[j].B - 2 * T[j].A, mp(T[j].W, 1)),
            b2.Upd(2 * T[j].B - T[j].A, mp(T[j].W, 1));
    }
  b1.Upd(0, mp(1, -1)), b2.Upd(0, mp(1, -1));
  for (int i = first[x]; i; i = eage[i].nxt)
    if (!yet[eage[i].t]) {
      tot = 0, cldfs(eage[i].t, 0, eage[i].op == 0, eage[i].op == 1, eage[i].w);
      for (int j = 1; j <= tot; ++j)
        b1.Upd(T[j].B - 2 * T[j].A, mp(qw(T[j].W, mod - 2), -1)),
            b2.Upd(2 * T[j].B - T[j].A, mp(qw(T[j].W, mod - 2), -1));
    }
  ans = mul(ans, res);
}
void TDQ(int x) {
  yet[x] = 1;
  cal(x);
  for (int i = first[x]; i; i = eage[i].nxt)
    if (!yet[eage[i].t]) {
      Ms = M = sz[eage[i].t];
      grdfs(eage[i].t, 0), TDQ(rt);
    }
}
int main() {
  read(n);
  ans = 1;
  b1.init();
  b2.init();
  for (int i = 1, op, x, y, z; i < n; ++i)
    read(x), read(y), read(z), read(op), ad(op, x, y, z), ad(op, y, x, z);
  M = Ms = n;
  grdfs(1, 0);
  TDQ(rt);
  printf("%d\n", ans);
  return 0;
}
