#include <bits/stdc++.h>
using namespace std;
const int MN = 100005, offset = 500000, P2 = (1 << 20), MTS = 2 * P2 + 5,
          inf = 1000000005, mod = 1000000007;
const long long INF = 1000000000000000005LL;
struct edge {
  int first, second, c;
};
int used[MN], blocked[MN], pod[MN], maxi[MN];
int S[MTS];
long long M[MTS];
vector<edge> G[MN];
vector<int> V;
int czas, cur_typ;
long long res = 1LL;
void add(int p, int v) {
  p += P2;
  while (p) {
    S[p] += v;
    p >>= 1;
  }
}
void mno(int p, long long v) {
  p += P2;
  while (p) {
    M[p] *= v;
    M[p] %= mod;
    p >>= 1;
  }
}
int sum(int a, int b) {
  a += P2, b += P2;
  int ret = 0;
  while (a < b) {
    if (a & 1) ret += S[a++];
    if (!(b & 1)) ret += S[b--];
    a >>= 1, b >>= 1;
  }
  if (a == b) ret += S[a];
  return ret;
}
long long ilo(int a, int b) {
  a += P2, b += P2;
  long long ret = 1LL;
  while (a < b) {
    if (a & 1) ret = (ret * M[a++]) % mod;
    if (!(b & 1)) ret = (ret * M[b--]) % mod;
    a >>= 1, b >>= 1;
  }
  if (a == b) ret *= M[a];
  return ret % mod;
}
long long pot(long long a, long long b) {
  if (b == 0LL) return 1LL;
  long long ret = pot(a, (b >> 1));
  ret = (ret * ret) % mod;
  if (b & 1LL) ret = (ret * a) % mod;
  return ret;
}
long long rev(long long x) { return pot(x, mod - 2); }
void dfsPod(int x) {
  used[x] = czas;
  pod[x] = 1, maxi[x] = 0;
  V.push_back(x);
  for (auto v : G[x])
    if (!blocked[v.first] && used[v.first] != czas) {
      dfsPod(v.first);
      pod[x] += pod[v.first];
      maxi[x] = max(maxi[x], pod[v.first]);
    }
}
int centro(int x) {
  ++czas;
  V.clear();
  dfsPod(x);
  int s = V.size(), hf = (s >> 1), ret = x;
  for (auto v : V)
    if (max(maxi[v], s - pod[v]) <= hf) ret = v;
  return ret;
}
inline int fun(int v) {
  v ^= cur_typ;
  if (v == 0)
    return -1;
  else
    return 2;
}
void dfsLicz(int x, int suma, long long ilocz) {
  used[x] = czas;
  if (cur_typ == 1) {
    int wyk = sum(0, offset - suma - 1);
    long long il = ilo(0, offset - suma - 1);
    res *= rev(il);
    res %= mod;
    res *= rev(pot(ilocz, wyk));
    res %= mod;
  } else {
    int wyk = sum(offset - suma, P2 - 5);
    long long il = ilo(offset - suma, P2 - 5);
    res *= il;
    res %= mod;
    res *= pot(ilocz, wyk);
    res %= mod;
  }
  for (auto v : G[x])
    if (!blocked[v.first] && used[v.first] != czas)
      dfsLicz(v.first, suma + fun(v.second), (ilocz * v.c) % mod);
}
void dfsDodaj(int x, int suma, long long ilocz, int r) {
  used[x] = czas;
  if (r == 0) {
    add(offset + suma, 1);
    mno(offset + suma, ilocz);
  } else {
    add(offset + suma, -1);
    mno(offset + suma, rev(ilocz));
  }
  for (auto v : G[x])
    if (!blocked[v.first] && used[v.first] != czas)
      dfsDodaj(v.first, suma + fun(v.second), (ilocz * v.c) % mod, r);
}
void licz(int x, int typ) {
  cur_typ = typ;
  add(offset, 1);
  for (auto v : G[x])
    if (!blocked[v.first]) {
      used[x] = ++czas;
      dfsLicz(v.first, fun(v.second), v.c);
      used[x] = ++czas;
      dfsDodaj(v.first, fun(v.second), v.c, 0);
    }
  for (auto v : G[x])
    if (!blocked[v.first]) {
      used[x] = ++czas;
      dfsDodaj(v.first, fun(v.second), v.c, 1);
    }
  add(offset, -1);
}
void decomp(int x, int typ) {
  x = centro(x);
  licz(x, typ);
  blocked[x] = 1;
  for (auto v : G[x])
    if (!blocked[v.first]) decomp(v.first, typ);
}
int main() {
  for (int i = 0; i < MTS; ++i) M[i] = 1LL;
  int n;
  scanf("%d", &n);
  for (int i = 1; i < n; ++i) {
    int u, v, x, c;
    scanf("%d%d%d%d", &u, &v, &x, &c);
    edge e1 = {u, c, x};
    edge e2 = {v, c, x};
    G[u].push_back(e2);
    G[v].push_back(e1);
  }
  decomp(1, 0);
  for (int i = 1; i <= n; ++i) blocked[i] = 0;
  decomp(1, 1);
  printf("%lld", res);
}
