#include <bits/stdc++.h>
using namespace std;
struct edge {
  int parent_node;
  int dest_node;
  unsigned long long weight;
  unsigned long long strength;
  unsigned long long min_strength;
  edge(int x, int y, unsigned long long w, unsigned long long s) {
    parent_node = x;
    dest_node = y;
    weight = w;
    strength = s;
    min_strength = s;
  }
  edge(){};
};
struct OrderedEdges {
  unsigned long long total_weight;
  list<int> q;
  bool good;
  OrderedEdges() {
    good = true;
    total_weight = 0;
  }
};
struct edge;
edge edges[200011];
int N;
struct OrderedEdges fix(int root, const vector<vector<int>>& outgoing) {
  OrderedEdges res = OrderedEdges();
  if (outgoing[root].empty()) return res;
  unsigned long long total_weight = 0;
  for (int e : outgoing[root]) {
    int dest_node = edges[e].dest_node;
    OrderedEdges edges_of_e = fix(dest_node, outgoing);
    if (!edges_of_e.good) return edges_of_e;
    if (edges_of_e.total_weight > edges[e].strength) {
      unsigned long long lose_target =
          edges_of_e.total_weight - edges[e].strength;
      while (lose_target > 0 && edges_of_e.q.size()) {
        int edge_key = edges_of_e.q.front();
        unsigned long long lose_amount =
            min(edges[edge_key].strength - edges[edge_key].min_strength,
                lose_target);
        edges_of_e.total_weight -= lose_amount;
        edges[edge_key].strength -= lose_amount;
        edges[edge_key].weight -= lose_amount;
        lose_target -= lose_amount;
        if (lose_target > 0) edges_of_e.q.pop_front();
      }
    }
    edges_of_e.q.push_back(e);
    total_weight += edges[e].weight;
    total_weight += edges_of_e.total_weight;
    res.q.splice(res.q.end(), edges_of_e.q);
  }
  res.total_weight = total_weight;
  return res;
}
void print_edges() {
  cout << N << endl;
  for (int i = 1; i < N; i++) {
    cout << edges[i].parent_node << " " << edges[i].dest_node << " "
         << edges[i].weight << " " << edges[i].strength << endl;
  }
}
unsigned long long minimal_weight_dfs(int root,
                                      const vector<vector<int>>& outgoing,
                                      bool* g) {
  if (outgoing[root].empty()) return 0;
  if (*g == false) return 0;
  unsigned long long total_weight = 0;
  for (int e : outgoing[root]) {
    unsigned long long subtree_weight =
        minimal_weight_dfs(edges[e].dest_node, outgoing, g);
    if (edges[e].strength >= subtree_weight) {
      unsigned long long slack =
          min(edges[e].strength - subtree_weight, edges[e].weight - 1);
      subtree_weight += edges[e].weight;
      subtree_weight -= slack;
      unsigned long long min_strength = edges[e].strength - slack;
      edges[e].min_strength = min_strength;
    } else {
      *g = false;
      return 0;
    }
    total_weight += subtree_weight;
  }
  return total_weight;
}
void solution(const vector<vector<int>>& outgoing) {
  bool good = true;
  minimal_weight_dfs(1, outgoing, &good);
  if (!good) {
    cout << "-1" << endl;
    return;
  }
  OrderedEdges res = fix(1, outgoing);
  if (res.good) {
    print_edges();
  } else {
    cout << "-1" << endl;
  }
}
int main() {
  cin >> N;
  vector<vector<int>> outgoing(N + 1, vector<int>());
  for (int i = 1; i < N; ++i) {
    int x;
    int y;
    unsigned long long w, p;
    cin >> x >> y >> w >> p;
    edges[i] = edge(x, y, w, p);
    outgoing[x].push_back(i);
  }
  solution(outgoing);
  return 0;
}
