#include <bits/stdc++.h>
const long long big = 100010;
long long n, EdgeSize, IdCnt, root, NodeCnt, sumx, sumy;
long long head[big], top[big], size[big], son[big], id[big], fa[big], dep[big],
    x[big], y[big];
long long c[2][big << 2];
double tag[big << 2], sum[big << 2], ans;
struct _Edge {
  long long v, next;
} e[big << 1];
inline long long read() {
  char c(getchar());
  long long f(1), x(0);
  for (; !isdigit(c); (c == '-') && (f = -1), c = getchar())
    ;
  for (; isdigit(c); x = (x << 1) + (x << 3) + (c ^ 48), c = getchar())
    ;
  return f * x;
}
inline void EdgeAdd(long long u, long long v) {
  e[EdgeSize] = (_Edge){v, head[u]};
  head[u] = EdgeSize++;
}
void dfs1(long long u, long long father) {
  fa[u] = father, dep[u] = dep[father] + 1;
  size[u] = 1;
  for (register int i(head[u]); ~i; i = e[i].next) {
    long long v = e[i].v;
    if (v == father) continue;
    dfs1(v, u);
    size[u] += size[v];
    if (size[son[u]] < size[v]) son[u] = v;
  }
}
void dfs2(long long u, long long top_) {
  top[u] = top_, id[u] = ++IdCnt;
  if (son[u]) dfs2(son[u], top_);
  for (register int i(head[u]); ~i; i = e[i].next) {
    long long v = e[i].v;
    if (v == fa[u] || v == son[u]) continue;
    dfs2(v, v);
  }
}
inline void PushDown(long long t, long long l, long long r) {
  if (tag[t] == 0) return;
  sum[c[0][t]] += tag[t], sum[c[1][t]] += tag[t];
  tag[c[0][t]] += tag[t], tag[c[1][t]] += tag[t];
  tag[t] = 0;
}
void BuildTree(long long &t, long long l, long long r) {
  if (!t) t = ++NodeCnt;
  if (l == r) return;
  long long mid((l + r) >> 1);
  BuildTree(c[0][t], l, mid), BuildTree(c[1][t], mid + 1, r);
}
void modify(long long t, long long l, long long r, long long x, long long y,
            double val) {
  if (x <= l && y >= r) {
    sum[t] += val, tag[t] += val;
    return;
  }
  PushDown(t, l, r);
  long long mid((l + r) >> 1);
  if (x <= mid) modify(c[0][t], l, mid, x, y, val);
  if (y > mid) modify(c[1][t], mid + 1, r, x, y, val);
}
double query(long long t, long long l, long long r, long long x) {
  if (l == r) return sum[t];
  PushDown(t, l, r);
  long long mid((l + r) >> 1);
  if (x <= mid)
    return query(c[0][t], l, mid, x);
  else
    return query(c[1][t], mid + 1, r, x);
}
int main(void) {
  memset(head, -1, sizeof head);
  n = read();
  for (register int i(1); i < n; ++i) {
    long long u = read(), v = read();
    EdgeAdd(u, v), EdgeAdd(v, u);
  }
  dfs1(1, 0), dfs2(1, 1), BuildTree(root, 1, n);
  for (register int i(1); i <= n; ++i)
    x[i] = read(), y[i] = read(), sumx += x[i], sumy += y[i];
  for (register int i(1); i <= n; ++i) {
    if (!y[i]) continue;
    double p = (double)y[i] / (double)sumy;
    for (register int j(head[i]); ~j; j = e[j].next) {
      long long v = e[j].v;
      if (v == fa[i]) continue;
      modify(root, 1, n, id[v], id[v] + size[v] - 1, p * size[v]);
    }
    if (id[i] - 1) modify(root, 1, n, 1, id[i] - 1, p * (n - size[i]));
    if (id[i] + size[i] <= n)
      modify(root, 1, n, id[i] + size[i], n, p * (n - size[i]));
  }
  for (register int i(1); i <= n; ++i) {
    if (!x[i]) continue;
    ans += query(root, 1, n, id[i]) * ((double)x[i] / (double)sumx);
  }
  printf("%.9lf\n", ans);
  return 0;
}
