- #pragma warning(disable:4786)
- //#pragma comment(linker, "/STACK:16777216")
- #pragma comment(linker, "/STACK:1073741824")
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<vector>
- #include<set>
- #include<map>
- #include<functional>
- #include<string>
- #include<cstring>
- #include<cstdlib>
- #include<queue>
- #include<utility>
- #include<fstream>
- #include<sstream>
- #include<cmath>
- #include<stack>
- #include<assert.h>
- #include<complex>
- #include<bitset>
- using namespace std;
-
- #define MEM(a, b) memset(a, (b), sizeof(a))
- #define CLR(a) memset(a, 0, sizeof(a))
- #define MAX(a, b) ((a) > (b) ? (a) : (b))
- #define MIN(a, b) ((a) < (b) ? (a) : (b))
- #define ABS(X) ( (X) > 0 ? (X) : ( -(X) ) )
- #define S(X) ( (X) * (X) )
- #define SZ(V) (int )V.size()
- #define FORN(i, n) for(i = 0; i < n; i++)
- #define FORAB(i, a, b) for(i = a; i <= b; i++)
- #define ALL(V) V.begin(), V.end()
-
- typedef pair<int,int> PII;
- typedef pair<double, double> PDD;
- typedef vector<int> VI;
-
- #define IN(A, B, C) assert( B <= A && A <= C)
-
- //typedef int LL;
- //typedef __int64 LL;
-
- vector<int> Prime;
- int mark[50002];
-
- void sieve(int n)
- {
- int i,j,limit=sqrt(n*1.)+2;
-
- mark[1] = 1;
- for(i=4;i<=n;i+=2) mark[i]=1;
-
- Prime.push_back(2);
- for(i=3;i<=n;i+=2)
- if(!mark[i])
- {
- Prime.push_back(i);
-
- if(i<=limit)
- {
- for(j=i*i;j<=n;j+=i*2)
- {
- mark[j] = 1;
- }
- }
- }
- }
-
-
- VI V[200003];
- vector<PII> E[200003];
- int n, ans, dummy;
- vector<int>::iterator iV;
-
- int xx;
-
- void Binarize(int at, int parent)
- {
- int x, y, sz, i;
-
- sz = V[at].size();
- // printf("%d %d\n", xx++, sz);
-
- if(parent)
- {
- E[at].push_back(PII(parent, at<=n));
- }
-
- if(sz <= 2)
- {
- for(i = 0; i < sz; i++)
- {
- if(at <= n)
- V[V[at][i]].erase( find(V[V[at][i]].begin(), V[V[at][i]].end(), at) );
-
- E[at].push_back(PII(V[at][i], 1));
- Binarize(V[at][i], at);
- }
- }
- else
- {
- x = dummy + 1;
- y = dummy + 2;
- dummy += 2;
-
- for(i = 0; i < sz; i++)
- {
- if(i < sz/2) V[x].push_back(V[at][i]);
- else V[y].push_back(V[at][i]);
-
- if(at <= n)
- V[V[at][i]].erase( find(V[V[at][i]].begin(), V[V[at][i]].end(), at) );
- }
-
- E[at].push_back( PII(x, 0) );
- E[at].push_back( PII(y, 0) );
-
- Binarize(x, at);
- Binarize(y, at);
- }
- }
-
- int subtree[200005], best_pos, best_value, best_d;
- int parent[200005], _sz;
-
- int DFS(int at, int parent)
- {
- subtree[at] = 1;
- ::parent[at] = parent;
-
- int here, sz = E[at].size(), i;
- for(i = 0; i < sz; i++)
- {
- if(E[at][i].first == parent)
- {
- here = E[at][i].second;
- continue;
- }
-
- subtree[at] += DFS(E[at][i].first, at);
- }
-
- if(parent && (best_pos == -1 || best_value > ABS(_sz/2 - subtree[at])))
- {
- best_pos = at, best_value = ABS(_sz/2 - subtree[at]), best_d = here;
- }
-
- return subtree[at];
- }
-
- void populate_depth(int at, int depth, int parent, vector<int> &V)
- {
- if(at <= n)
- V.push_back(depth);
-
- int i, sz = E[at].size();
- for(i = 0; i < sz; i++)
- {
- if(E[at][i].first == parent) continue;
-
- populate_depth(E[at][i].first, depth + E[at][i].second, at, V);
- }
- }
-
- typedef complex<double> base;
- double PI = acos(-1.);
-
- void fft (vector<base> & a, bool invert) {
- int n = (int) a.size();
-
- for (int i=1, j=0; i<n; ++i) {
- int bit = n >> 1;
- for (; j>=bit; bit>>=1)
- j -= bit;
- j += bit;
- if (i < j)
- swap (a[i], a[j]);
- }
-
- for (int len=2; len<=n; len<<=1) {
- double ang = 2*PI/len * (invert ? -1 : 1);
- base wlen (cos(ang), sin(ang));
- for (int i=0; i<n; i+=len) {
- base w (1);
- for (int j=0; j<len/2; ++j) {
- base u = a[i+j], v = a[i+j+len/2] * w;
- a[i+j] = u + v;
- a[i+j+len/2] = u - v;
- w *= wlen;
- }
- }
- }
- if (invert)
- for (int i=0; i<n; ++i)
- a[i] /= n;
- }
-
- void multiply (const vector<int> & a, const vector<int> & b, vector<int> & res) {
- vector<base> fa, fb;
- int i;
-
- int sz = a.size();
- for(i = 0; i < sz; i++)
- fa.push_back( a[i] );
-
- sz = b.size();
- for(i = 0; i < sz; i++)
- fb.push_back( b[i] );
-
- size_t n = 1;
- while (n < MAX (a.size(), b.size())) n <<= 1;
- n <<= 1;
- fa.resize (n), fb.resize (n);
-
- fft (fa, false), fft (fb, false);
- for (i=0; i<n; ++i)
- fa[i] *= fb[i];
- fft (fa, true);
-
- res.resize (n);
- for (i=0; i<n; ++i)
- res[i] = int (fa[i].real() + 0.5);
- }
-
- void f(vector<int> &X, vector<int> &Y)
- {
- int i, maxx = 0;
- for(i = X.size() - 1; i >= 0; i--) maxx = MAX(X[i], maxx);
- for(i = Y.size() - 1; i >= 0; i--) maxx = MAX(Y[i], maxx);
-
- vector<int> A(maxx + 1, 0), B(maxx + 1, 0), C;
- for(i = X.size() - 1; i >= 0; i--) A[X[i]]++;
- for(i = Y.size() - 1; i >= 0; i--) B[Y[i]]++;
-
-
- // printf(">>>>\n");
- // for(i = A.size() - 1; i >= 0; i--) printf("%d, ", A[i]); printf("\n");
- // for(i = B.size() - 1; i >= 0; i--) printf("%d, ", B[i]); printf("\n");
- multiply(A, B, C);
-
- // for(i = C.size() - 1; i >= 0; i--) printf("%d, ", C[i]); printf("\n");
-
- maxx = C.size();
- int sz = Prime.size();
- for(i = 0; i < sz && Prime[i] < maxx; i++)
- ans += C[Prime[i]];
- }
-
- queue<PII> Q;
-
- void isTree()
- {
- queue<int> Q;
- int vis[50004];
- int u, i;
-
- MEM(vis, 0);
- vis[1] = 1;
- Q.push(1);
- while(!Q.empty())
- {
- u = Q.front();
- Q.pop();
-
- for(i = V[u].size() - 1; i >= 0; i--)
- if(vis[V[u][i]]==0)
- {
- vis[V[u][i]] = 1;
- Q.push( V[u][i] );
- }
- }
-
- for(i = 1; i <= n; i++)
- assert(vis[i]);
- }
-
- int main()
- {
- int i, a, b, j;
- PII u;
- vector<int> X, Y;
-
- sieve(50002);
-
- scanf("%d", &n);
- IN(n, 2, 50000);
- for(i = 1; i < n; i++)
- {
- scanf("%d %d", &a, &b);
-
- IN(a, 1, n);
- IN(b, 1, n);
-
- V[a].push_back(b);
- V[b].push_back(a);
- }
-
- isTree();
-
- dummy = n;
-
- //Make the tree binary. If there is a node with many children, keep one child left and make other children
- //the children of the right node. make the cost to right child 0. other 1.
- //In this tree, the cost of the path from an original node to another original node is same.
- Binarize(1, 0);
-
-
- /*
- printf("%d\n", ans);
- for(i = 1; i <= dummy; i++)
- {
- printf("%d:", i);
- for(j = 0; j < E[i].size(); j++)
- printf(" (%d, %d)", E[i][j].first, E[i][j].second);
- printf("\n");
- }
- */
-
- //Now find center of the tree. center of the tree is a node, having <=n/3 nodes in each subtree if
- //this node is deleted.
- //Now delete the link to its parent. For each subtree solve recursively.
- //For inter subtree path, list up all the distances to the original nodes in each subtree. Find the solution using FFT
- int x, y;
-
- int dd = 0;
- Q.push( PII(1, dummy) );
- while(!Q.empty())
- {
- u = Q.front();
- Q.pop();
-
- _sz = u.second;
-
- if(_sz == 1) continue;
-
- best_pos = -1;
- best_value = u.second;
-
- DFS(u.first, 0);
-
- x = best_pos;
- y = parent[x];
-
- E[x].erase( find(E[x].begin(), E[x].end(), PII(y, best_d)) );
- E[y].erase( find(E[y].begin(), E[y].end(), PII(x, best_d)) );
-
- Q.push( PII(x, subtree[x]) );
- Q.push( PII(y, _sz - subtree[x]) );
-
- X.clear();
- Y.clear();
-
- populate_depth(x, 0, 0, X);
- populate_depth(y, 0, 0, Y);
-
- if(best_d) for(i = X.size() - 1; i >= 0; i--) X[i]++;
- f(X, Y);
- }
-
- // printf("%d\n", ans);
- double f = (1.*ans)/( (n*(n-1.))/2 );
- printf("%.12lf\n", f);
-
- return 0;
- }