import std.stdio;
import std.ascii;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.random;
import std.regex;
import std.typecons;

int N;

struct Edge {
    int from, to, cost;
}

Edge[][] G;

bool input() {
    scanf("%d\n", &N);
    if (N == 0) return false;
    G = new Edge[][N];
    foreach (i; 0 .. N) {
        foreach (j; 0 .. 2) {
            int a, cost;
            scanf("%d %d", &a, &cost);
            G[i] ~= Edge(i, a, cost);
        }
    }
    return true;
}

void solve() {

    auto used = new bool[N];

    Edge[] cycle(int v) {
        Edge[] es;
        void dfs(int v) {
            foreach (e; G[v]) {
                if (used[e.to]) continue;
                used[e.to] = true;
                es ~= e;
                dfs(e.to);
            }
        }
        dfs(v);
        return es;
    }

    const MOD = 10007;
    int ret = 1;
    foreach (int i; 0 .. N) {
        if (used[i]) continue;
        used[i] = true;
        auto es = cycle(i);
        auto m = es.map!"a.cost".reduce!max;
        ret = ret * es.count!((a) => a.cost == m) % MOD;
    }
    writeln(ret);

}

void main() {
    while (input) solve;
}