#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 100005;
int n, ans = 1;
bool vis[maxn], iscenter[maxn];
int siz[maxn];
struct edge {
  int to, zne, color;
};
vector<edge> gr[maxn];
vector<int> cd[maxn];
int poww(int x, int p) {
  if (p == 0) return 1;
  if (p == 1) return x;
  int t = poww(x, p >> 1);
  t = (1LL * t * t) % mod;
  if (p & 1) t = (1LL * t * x) % mod;
  return t;
}
struct node {
  int key, prior, zhel, zne, cnt;
  node *l, *r;
  node(){};
  node(int _key, int _zne) {
    zne = zhel = _zne;
    key = _key;
    cnt = 1;
    prior = rand();
    l = r = 0;
  }
};
void upd(node *&t) {
  if (t) {
    t->zhel = t->zne;
    t->cnt = 1;
    if (t->l) t->cnt += t->l->cnt, t->zhel = (1LL * t->zhel * t->l->zhel) % mod;
    if (t->r) t->cnt += t->r->cnt, t->zhel = (1LL * t->zhel * t->r->zhel) % mod;
  }
}
void merge(node *&t, node *l, node *r) {
  if (!l || !r)
    t = (l ? l : r);
  else {
    if (l->prior > r->prior)
      merge(l->r, l->r, r), t = l;
    else
      merge(r->l, l, r->l), t = r;
  }
  upd(t);
}
void split(node *t, node *&l, node *&r, int key) {
  if (!t)
    l = r = 0;
  else {
    if (t->key <= key)
      split(t->r, t->r, r, key), l = t;
    else
      split(t->l, l, t->l, key), r = t;
    upd(l);
    upd(r);
  }
}
void insert(node *&t, int key, int zne) {
  node *l, *r;
  split(t, l, r, key);
  node *md = new node(key, zne);
  merge(t, l, md);
  merge(t, t, r);
}
int dfs(int v) {
  vis[v] = true;
  siz[v] = 1;
  for (edge u : gr[v]) {
    if (!vis[u.to] && !iscenter[u.to]) siz[v] += dfs(u.to);
  }
  return siz[v];
}
int get_centr(int v, int sz) {
  bool fnd = true;
  int biggest = -1;
  vis[v] = true;
  for (edge u : gr[v]) {
    if (!vis[u.to] && !iscenter[u.to]) {
      if (siz[u.to] > sz / 2) fnd = false;
      if (biggest == -1 || siz[u.to] > siz[biggest]) biggest = u.to;
    }
  }
  if (fnd && sz <= 2 * siz[v])
    return v;
  else
    return get_centr(biggest, sz);
}
int get_centroid(int root) {
  memset(vis, false, sizeof(vis));
  memset(siz, 0, sizeof(siz));
  int sz = dfs(root);
  memset(vis, false, sizeof(vis));
  int centr = get_centr(root, sz);
  iscenter[centr] = true;
  return centr;
}
struct put {
  int kleik, cr, cb;
};
vector<put> vsp;
void get_vsp(int v, int cr, int cb, int kleik, int par) {
  vsp.push_back({kleik, cr, cb});
  for (edge u : gr[v]) {
    if (!iscenter[u.to] && par != u.to)
      get_vsp(u.to, cr + 1 - u.color, cb + u.color, (1LL * kleik * u.zne) % mod,
              v);
  }
}
int decomp(int v) {
  int root = get_centroid(v);
  int ann = 1, del = 1;
  node *t1 = 0, *t2 = 0;
  for (edge u : gr[root]) {
    if (!iscenter[u.to]) {
      vsp.clear();
      get_vsp(u.to, 1 - u.color, u.color, u.zne, -1);
      for (put a : vsp) {
        node *l, *r;
        int step = 0;
        split(t1, l, r, 2 * a.cr - a.cb);
        if (l) ann = (1LL * ann * l->zhel) % mod;
        if (l) step = l->cnt;
        merge(t1, l, r);
        split(t2, l, r, 2 * a.cb - a.cr);
        if (r) del = (1LL * del * r->zhel) % mod;
        if (r) step -= r->cnt;
        merge(t2, l, r);
        ans = (1LL * ans * poww(a.kleik, step)) % mod;
        if (2 * a.cb >= a.cr && 2 * a.cr >= a.cb)
          ans = (1LL * ans * a.kleik) % mod;
      }
      for (put a : vsp) {
        insert(t1, a.cb - 2 * a.cr, a.kleik);
        insert(t2, a.cr - 2 * a.cb, a.kleik);
      }
    }
  }
  ann = (1LL * ann * poww(del, mod - 2)) % mod;
  ans = (1LL * ans * ann) % mod;
  for (edge u : gr[root]) {
    if (!iscenter[u.to]) {
      int v = decomp(u.to);
      cd[v].push_back(root);
      cd[root].push_back(v);
    }
  }
  return root;
}
int main() {
  srand(137657);
  ios_base::sync_with_stdio(false);
  cin >> n;
  for (int i = 1; i < n; ++i) {
    int u, v, zne, col;
    cin >> u >> v >> zne >> col;
    gr[u].push_back({v, zne, col});
    gr[v].push_back({u, zne, col});
  }
  int cdroot = decomp(1);
  cout << ans;
  return 0;
}
