#define TASKNAME "lanes"
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cassert>
#include <ctime>

#define sz(a) (int)a.size()

using namespace std;

typedef unsigned long long ll;
typedef pair <int, int> pii;
typedef vector <pii> vpii;

const int maxn = 1e5;

struct edge {
  int v, cost, isGood;

  edge() {v = cost = isGood = 0;}
  edge(int v, int cost, int isGood) : v(v), cost(cost), isGood(isGood) {}
};

int n;
vector <edge> gr[maxn];
int p[maxn], isGood[maxn], w[maxn];
int tin[maxn], tout[maxn], timer;

bool isAncestor(int v, int u) {
  return tin[v] <= tin[u] && tout[v] >= tout[u];
}

void dfs(int v, int pr) {
  tin[v] = timer++;
  for (int i = 0; i < sz(gr[v]); i++) {
    int u = gr[v][i].v;
    if (u == pr)
      continue;
    p[u] = v;
    isGood[u] = gr[v][i].isGood;
    w[u] = gr[v][i].cost;
    dfs(u, v);
  }
  tout[v] = timer++;
}

int main() {
  freopen(TASKNAME".in", "r", stdin);
  freopen(TASKNAME".out", "w", stdout);
  scanf("%d", &n);
  assert(n <= 100);
  for (int i = 0; i < n - 1; i++) {
    int a, b, c, isGood;
    scanf("%d%d%d%d", &a, &b, &c, &isGood);
    --a, --b;
    gr[a].push_back(edge(b, c, isGood));
    gr[b].push_back(edge(a, c, isGood));
  }
  dfs(0, -1);

  ll paths = 0, answer = 0;
  for (int i = 0; i < n; i++)
    for (int j = i + 1; j < n; j++) {
      int v = i;
      bool haveGood = 0;
      ll cost = 0;
      while (!isAncestor(v, j))
        haveGood |= isGood[v], cost += w[v], v = p[v];
      int u = j;
      while (u != v)
        haveGood |= isGood[u], cost += w[u], u = p[u];
      if (haveGood)
        ++paths, answer += cost;
    }
           
  if (!paths)
    printf("0.0\n");
  else
    printf("%.20lf\n", answer * 1.0 / paths);
  return 0;                 
}