#include <cstdio>
#include <set>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int INF = 1e9 + 10;
const int N = 1e5 + 10;
#define NAME "evacuation"

struct edge {
    int to, l, t;
    edge(int to, int l, int t): to(to), l(l), t(t) {}
};

vector <edge> g[N];
int dp[N], sm[N], ans;

void calcDp(int v, int p) {
    if (g[v].size() == 1)
        dp[v] = INF;
    else
        dp[v] = -INF;
    for (int i = 0; i < (int)g[v].size(); ++i) {
        int to = g[v][i].to;
        if (to == p) continue;
        sm[to] = sm[v] + g[v][i].l;
        calcDp(to, v);
        dp[v] = max(dp[v], min(dp[to], g[v][i].t) - g[v][i].l);
    }
}

void merge(multiset <int>& a, multiset <int>& b) {
    for (multiset<int>::iterator it = a.begin(); it != a.end(); ++it)
        b.insert(*it);
}

void dfs(int v, int p, multiset <int>& s) {
    for (int i = 0; i < (int)g[v].size(); ++i) {
        int to = g[v][i].to;
        if (to == p) continue;
        multiset <int> son;
        dfs(to, v, son);
        while (son.size() > 0) {
            multiset <int>::iterator it = son.end();
            it--;
            if (*it <= g[v][i].t + sm[v])
                break;
            son.erase(it);
        }
        while (son.size() > 0 && *son.begin() <= dp[v] + sm[v]) {
            son.erase(son.begin());
            ++ans;
        }
        /*if (son.size() < s.size()) merge(son, s);
        else {
            merge(s, son);
            s.swap(son);
        }*/
        merge(s, son);
        s.swap(son);
    }
    if (dp[v] < 0) s.insert(sm[v]);
}


int main() {
	freopen(NAME".in", "r", stdin);
	freopen(NAME".out", "w", stdout);
    int n;
    cin >> n;
    for (int i = 0; i < n - 1; ++i) {
        int x, y, li, ti;
        scanf("%d%d%d%d", &x, &y, &li, &ti);
        --x;--y;
        g[x].push_back(edge(y, li, ti));
        g[y].push_back(edge(x, li, ti));
    }

    if (n <= 2) {
        cout << n;
        return 0;
    }

    int root;
    for (int i = 0; i < n; ++i)
        if (g[i].size() != 1) {
            root = i;
            break;
        }
    calcDp(root, -1);

    for (int i = 0; i < n; ++i)
        ans += dp[i] >= 0;
    multiset <int> s;
    dfs(root, -1, s);
    cout << ans;
    return 0;
}
