这个题其实就是求
为什么呢?考虑一个点i,枚举每一个j,
他对答案贡献的条件是在j作为点分树根
即i到j之间上没有点被选为点分树根
于是就点分,这个东西就是一个卷积,用fft即可
为什么我一写就是第一页...
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf (1<<30)
#define maxn 30011
using namespace std;
typedef double ldb;
const ldb pi=acos(-1);
const ldb eps=1e-7;
struct edge{
int r,nxt;
}e[maxn<<1];
struct complex{
ldb a,b;
complex(){}
complex(ldb a,ldb b):a(a),b(b){}
complex operator+(const complex& c)const{
return complex(a+c.a,b+c.b);
}
complex operator-(const complex& c)const{
return complex(a-c.a,b-c.b);
}
complex operator*(const complex& c)const{
return complex(a*c.a-b*c.b,a*c.b+b*c.a);
}
void clear(){a=b=0;}
}a[maxn],b[maxn];
bool vis[maxn];
int n,head[maxn],esz,size[maxn],num,rt,mn,bh[maxn],len1=0,len2=0,ma[maxn],mb[maxn];
ldb pre[maxn];
ldb ans;
void addedge(int u,int v){
e[++esz].r=v;e[esz].nxt=head[u];head[u]=esz;
}
void dfs1(int u,int f){
num++;
for(int t=head[u];t;t=e[t].nxt)
if(e[t].r!=f&&!vis[e[t].r])dfs1(e[t].r,u);
}
void dfs2(int u,int f){
size[u]=1;
int ans=-inf;
for(int t=head[u];t;t=e[t].nxt)
if(e[t].r!=f&&!vis[e[t].r])
dfs2(e[t].r,u),size[u]+=size[e[t].r],ans=max(ans,size[e[t].r]);
ans=max(ans,num-size[u]);
if(ans<mn)mn=ans,rt=u;
}
void findroot(int u){
num=0;mn=inf;
dfs1(u,u);dfs2(u,u);
}
void dft(complex h[],int n,int flag){
for(int i=0;i<n;++i)if(i<bh[i])swap(h[i],h[bh[i]]);
for(int i=1;i<n;i<<=1){
complex wn(cos(pi/i),sin(flag*pi/i));
for(int j=0;j<n;j+=(i<<1)){
complex w(1,0);
for(int k=0;k<i;++k){
complex x=h[j+k];
complex y=w*h[j+k+i];
h[j+k]=x+y;
h[j+k+i]=x-y;
w=w*wn;
}
}
}
if(flag==-1)for(int i=0;i<n;++i)h[i].a/=n;
}
void fft(int len1,int x[],int len2,int y[]){
if(!len1)return ;
int n=max(len1,len2),m=2*n,k=0;
for(n=1;n<=m;n<<=1)k++;
for(int i=0;i<n;++i)bh[i]=0;
for(int i=0;i<n;++i)bh[i]=((bh[i>>1]>>1)|((i&1)<<(k-1)));
// putchar(10);
for(int i=0;i<=n;++i)a[i].clear();
for(int i=0;i<=n;++i)b[i].clear();
for(int i=0;i<=len1;++i)a[i].a=x[i];
for(int i=0;i<=len2;++i)b[i].a=y[i];
dft(a,n,1);dft(b,n,1);
for(int i=0;i<=n;++i)a[i]=a[i]*b[i];
dft(a,n,-1);
for(int i=0;i<=m;++i)ans+=pre[i+1]*(int)(a[i].a+0.1);
}
void dfs3(int u,int f,int d){
mb[d]++;
ans+=pre[d+1];
len2=max(len2,d);
for(int t=head[u];t;t=e[t].nxt)if(e[t].r!=f&&!vis[e[t].r])
dfs3(e[t].r,u,d+1);
}
void dfs4(int u,int f,int d){
ma[d]++;mb[d]=0;
len1=max(len1,d);
for(int t=head[u];t;t=e[t].nxt)if(e[t].r!=f&&!vis[e[t].r])
dfs4(e[t].r,u,d+1);
}
void clean(int u,int f,int d){
ma[d]=mb[d]=0;
for(int t=head[u];t;t=e[t].nxt)if(e[t].r!=f&&!vis[e[t].r])
clean(e[t].r,u,d+1);
}
void solve(int u){
findroot(u);
vis[rt]=1;
// printf("[%d]",rt);
len1=len2=0;
for(int t=head[rt];t;t=e[t].nxt)if(!vis[e[t].r]){
dfs3(e[t].r,rt,1);
// for(int i=1;i<=n;++i)printf("[%d:%d,%d]",i,mb[i],ma[i]);
// puts("");
fft(len1,ma,len2,mb);
dfs4(e[t].r,rt,1);
}
clean(rt,rt,0);
for(int t=head[rt];t;t=e[t].nxt)if(!vis[e[t].r])
solve(e[t].r);
}
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;++i)pre[i]=1.0/((double)i);
for(int i=1,u,v;i<n;++i)
scanf("%d%d",&u,&v),u++,v++,
addedge(u,v),addedge(v,u);
solve(1);
printf("%.4lf",ans*2+n);
}