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

#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 size[maxn];
ll dp[2][maxn], ans[2][maxn];
ll pathsCount[2][maxn];
ll ONE = 1;
bool was[2][maxn];

void dfs(int v, int p, int needGood, int num) {
  size[v] = 1;
  was[num][v] = 1;
  int sumSizes = 0;
  for (int i = 0; i < sz(gr[v]); i++) {
    int u = gr[v][i].v;
    if (u == p || gr[v][i].isGood > needGood)
      continue;
    dfs(u, v, needGood, num);
    dp[num][v] += dp[num][u] + ONE * size[u] * gr[v][i].cost;
    pathsCount[num][v] += size[u];
    sumSizes += size[u];
    size[v] += size[u];         
  }

  ans[num][v] = dp[num][v];
  ll add = 0;
  for (int i = 0; i < sz(gr[v]); i++) {
    int u = gr[v][i].v;
    if (u == p || gr[v][i].isGood > needGood)
      continue;
    add += ONE * size[u] * (sumSizes - size[u]);
    ans[num][v] += (dp[num][u] + ONE * gr[v][i].cost * size[u]) * (sumSizes - size[u]);
  }      
  pathsCount[num][v] += add / 2;
}

int main() {
  freopen(TASKNAME".in", "r", stdin);
  freopen(TASKNAME".out", "w", stdout);
  scanf("%d", &n);
  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));
  }

  for (int i = 0; i < n; i++) {
    if (!was[0][i])
      dfs(i, -1, 1, 0);
    if (!was[1][i])
      dfs(i, -1, 0, 1);
  }
  
  ll answer = 0, paths = 0;
  for (int i = 0; i < n; i++) {
    answer += ans[0][i] - ans[1][i];
    paths += pathsCount[0][i] - pathsCount[1][i];
  }
  if (!paths)
    printf("0.0\n");
  else
    printf("%.20lf\n", answer * 1.0 / paths);
  return 0;                 
}