#include <bits/stdc++.h>   using namespace std;   const int N = 3e5 + 5, P = 1e9 + 7;   struct Edge {     int v, nxt, col;     long long w;   } e[N << 1];   int head[N], size = 1, ext;   long long ans = 1;   long long qpow(long long a, long long b) {     long long res = 1;     while (b) {       if (b & 1) res = res * a % P;       a = a * a % P;       b >>= 1;     }     return res;   }   void link(int u, int v, long long w, int col) {     e[++size].v = v;     e[size].nxt = head[u];     e[size].w = w;     e[size].col = col;     head[u] = size;   }   int read() {     int x = 0, f = 1;     char c = getchar();     while (c >  9  || c <  0 ) {       if (c ==  - ) f = -1;       c = getchar();     }     while (c >=  0  && c <=  9 ) {       x = x * 10 + c -  0 ;       c = getchar();     }     return x * f;   }   namespace sdh {   struct Node {     int v, w, col;     Node() {}     Node(int _v, int _w, int _col) {       v = _v;       w = _w;       col = _col;     }   } stk[N];   int top;   vector<Node> e[N];   void dfs(int u, int fa) {     top = 0;     for (Node v : e[u]) {       if (v.v == fa) continue;       stk[++top] = v;     }     int lst = u;     for (int i = 1; i <= top - 2; ++i) {       Node c = stk[i];       link(lst, c.v, c.w, c.col);       link(c.v, lst, c.w, c.col);       ++ext;       link(lst, ext, 1, -1);       link(ext, lst, 1, -1);       lst = ext;     }     if (top > 0)       link(lst, stk[top].v, stk[top].w, stk[top].col),           link(stk[top].v, lst, stk[top].w, stk[top].col);     if (top > 1)       link(lst, stk[top - 1].v, stk[top - 1].w, stk[top - 1].col),           link(stk[top - 1].v, lst, stk[top - 1].w, stk[top - 1].col);     for (Node v : e[u]) {       if (v.v == fa) continue;       dfs(v.v, u);     }   }   }  // namespace sdh   int max(int x, int y) { return x > y ? x : y; }   int n, RT, MN, sze[N], SZE;   bool vis[N << 1];   void findrt(int u, int fa) {     sze[u] = 1;     for (int i = head[u]; i; i = e[i].nxt) {       int v = e[i].v;       if (v == fa || vis[i]) continue;       findrt(v, u);       sze[u] += sze[v];       if (MN > max(sze[v], SZE - sze[v])) {         MN = max(sze[v], SZE - sze[v]);         RT = i;       }     }   }   struct Q {     int x, y, opt;     long long val;   } q[N], type[N];   bool cmp(Q p, Q q) {     if (p.x != q.x)       return p.x < q.x;     else       return p.opt < q.opt;   }   int tot;   void dfsA(int u, int fa, int B, int W, long long val) {     if (u <= n) {       q[++tot].x = 2 * W - B;       q[tot].y = 2 * B - W;       q[tot].val = val;       q[tot].opt = 1;     }     for (int i = head[u]; i; i = e[i].nxt) {       int v = e[i].v;       if (v == fa || vis[i]) continue;       if (e[i].col == 0) dfsA(v, u, B + 1, W, val * e[i].w % P);       if (e[i].col == 1) dfsA(v, u, B, W + 1, val * e[i].w % P);       if (e[i].col == -1) dfsA(v, u, B, W, val * e[i].w % P);     }   }   void dfsB(int u, int fa, int B, int W, long long val) {     if (u <= n) {       q[++tot].x = B - 2 * W;       q[tot].y = W - 2 * B;       q[tot].val = val;       q[tot].opt = 0;     }     for (int i = head[u]; i; i = e[i].nxt) {       int v = e[i].v;       if (v == fa || vis[i]) continue;       if (e[i].col == 0) dfsB(v, u, B + 1, W, val * e[i].w % P);       if (e[i].col == 1) dfsB(v, u, B, W + 1, val * e[i].w % P);       if (e[i].col == -1) dfsB(v, u, B, W, val * e[i].w % P);     }   }   void Cdq(int l, int r) {     if (l >= r) return;     int mid = (l + r) >> 1;     Cdq(l, mid);     Cdq(mid + 1, r);     long long sum = 0, prod = 1;     int i = l, j = mid + 1;     while (j <= r) {       while (i <= mid && q[i].y <= q[j].y) {         if (q[i].opt == 0) {           ++sum;           (prod *= q[i].val) %= P;         }         ++i;       }       if (q[j].opt == 1) {         ans = ans * qpow(q[j].val, sum) % P * prod % P;       }       ++j;     }     i = l;     j = mid + 1;     int tot = 0;     while (i <= mid && j <= r) {       if (q[i].y < q[j].y)         type[++tot] = q[i++];       else         type[++tot] = q[j++];     }     while (i <= mid) type[++tot] = q[i++];     while (j <= r) type[++tot] = q[j++];     for (int i = l; i <= r; ++i) q[i] = type[i - l + 1];   }   void calc(int u) {     int U = e[u].v, V = e[u ^ 1].v;     tot = 0;     if (e[u].col == 0) dfsA(U, 0, 1, 0, e[u].w);     if (e[u].col == 1) dfsA(U, 0, 0, 1, e[u].w);     if (e[u].col == -1) dfsA(U, 0, 0, 0, e[u].w);     dfsB(V, 0, 0, 0, 1);     sort(q + 1, q + tot + 1, cmp);     Cdq(1, tot);   }   void Divide(int u) {     if (!u) return;     vis[u] = vis[u ^ 1] = 1;     calc(u);     int U = e[u].v, V = e[u ^ 1].v, totsze = SZE, szeU = sze[U], szeV = sze[V];     RT = 0;     MN = P;     SZE = szeU > szeV ? totsze - szeV : szeU;     findrt(U, 0);     Divide(RT);     RT = 0;     MN = P;     SZE = szeV > szeU ? totsze - szeU : szeV;     findrt(V, 0);     Divide(RT);   }   int main() {     n = read();     for (int i = 1; i < n; ++i) {       int u = read(), v = read(), w = read(), col = read();       sdh::e[u].push_back(sdh::Node(v, w, col));       sdh::e[v].push_back(sdh::Node(u, w, col));     }     ext = n;     sdh::dfs(1, 0);     RT = 0;     SZE = ext;     MN = P;     findrt(1, 0);     Divide(RT);     printf( %lld , ans);     return 0;   }