#include <bits/stdc++.h>
using namespace std;
inline int ask(int x) {
  printf("? %d\n", x);
  fflush(stdout);
  int ret;
  scanf("%d", &ret);
  return ret;
}
vector<int> v[200005];
int n, k, tp;
int x[200005], y[200005], w[200005], p[200005];
int par[200005];
long long tree[4 * 200005];
long long butuh[200005];
long long str[200005];
long long wei[200005];
long long depth[200005];
pair<int, int> arr[200005];
priority_queue<pair<int, int> > pq[200005];
int in[200005], out[200005], TIME;
pair<int, int> tree2[4 * 200005];
pair<int, int> banding(pair<int, int> a, pair<int, int> b) {
  if (a.first > b.first) return a;
  return b;
}
void upd(int now, int l, int r, int pos, int depth, int ccd) {
  if (l == r) {
    tree2[now] = make_pair(depth, ccd);
    return;
  }
  int mid = (l + r) >> 1;
  if (pos <= mid)
    upd(now << 1, l, mid, pos, depth, ccd);
  else
    upd(now << 1 | 1, mid + 1, r, pos, depth, ccd);
  tree2[now] = banding(tree2[now << 1], tree2[now << 1 | 1]);
}
pair<int, int> que(int now, int l, int r, int a, int b) {
  if (r < a || l > b) return make_pair(-1, 0);
  if (a <= l && r <= b) return tree2[now];
  int mid = (l + r) >> 1;
  return banding(que(now << 1, l, mid, a, b),
                 que(now << 1 | 1, mid + 1, r, a, b));
}
void dfsss(int now, int L) {
  depth[now] = L;
  int size = v[now].size();
  butuh[now] = 0;
  ++TIME;
  in[now] = TIME;
  for (int i = 0; i < size; i++) {
    int next = v[now][i];
    dfsss(next, L + 1);
    butuh[now] += butuh[next] + wei[next];
  }
  arr[++tp] = make_pair(depth[now], now);
  out[now] = TIME;
}
bool gagal = false;
void update(int now, int l, int r, int pos, int val) {
  if (l == r) {
    tree[now] += val;
    return;
  }
  int mid = (l + r) >> 1;
  if (pos <= mid)
    update(now << 1, l, mid, pos, val);
  else
    update(now << 1 | 1, mid + 1, r, pos, val);
  tree[now] = tree[now << 1] + tree[now << 1 | 1];
}
inline long long query(int now, int l, int r, int a, int b) {
  if (r < a || l > b) return 0;
  if (a <= l && r <= b) return tree[now];
  int mid = (l + r) >> 1;
  return query(now << 1, l, mid, a, b) + query(now << 1 | 1, mid + 1, r, a, b);
}
void dfs(int now) {
  if (gagal) return;
  int size = v[now].size();
  for (int i = 0; i < size; i++) {
    int next = v[now][i];
    dfs(next);
  }
  if (now == 1) return;
  if (size == 0) {
    upd(1, 1, n, in[now], depth[now], now);
  } else {
    long long val = query(1, 1, n, in[now], out[now]);
    if (butuh[now] - val <= str[now]) {
      upd(1, 1, n, in[now], depth[now], now);
    } else {
      while (true) {
        long long val = query(1, 1, n, in[now], out[now]);
        long long krg = (butuh[now] - val) - str[now];
        if (krg == 0) break;
        pair<int, int> res = que(1, 1, n, in[now], out[now]);
        int find = res.second;
        int ret = res.first;
        if (res.first == -1) {
          gagal = true;
          return;
        }
        long long val2 = query(1, 1, n, in[find], out[find]);
        long long potential =
            min(str[find] - (butuh[find] - val2), wei[find] - 1);
        if (potential > krg) {
          str[find] = str[find] - krg;
          wei[find] = wei[find] - krg;
          update(1, 1, n, in[par[find]], krg);
          break;
        } else {
          str[find] = str[find] - potential;
          wei[find] = wei[find] - potential;
          update(1, 1, n, in[par[find]], potential);
          upd(1, 1, n, in[find], -1, find);
        }
      }
    }
  }
  upd(1, 1, n, in[now], depth[now], now);
}
int main() {
  for (int i = 1; i < 4 * 200005; i++) tree2[i] = make_pair(-1, 0);
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    scanf("%d %d %d %d", &x[i], &y[i], &w[i], &p[i]);
    str[y[i]] = p[i];
    wei[y[i]] = w[i];
    par[y[i]] = x[i];
    v[x[i]].push_back(y[i]);
  }
  dfsss(1, 1);
  dfs(1);
  if (gagal) {
    printf("-1\n");
    return 0;
  }
  printf("%d\n", n);
  for (int i = 1; i < n; i++) {
    printf("%d %d %lld %lld\n", x[i], y[i], wei[y[i]], str[y[i]]);
  }
}
