這個只要知道兩個子樹連在一起的直徑端點必然是各自直徑的端點就好了
然後瞎枚舉一通
只要知道 ∑i∑jmin{sizei,sizej},∑isizei=n \sum_i\sum_j min\{size_i,size_j\} ,\sum_i size_i=n是 O(nn√) O(n\sqrt n)的就好了
#include<cstdio>#include<cstdlib>#include<algorithm>#include<vector>#include<map>#define pb push_backusing namespace std;typedef pair<int,int> abcd;typedef long long ll;inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005;struct edge{ int u,v,next;}G[N<<1];int head[N],inum;inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;}#define V G[p].vint depth[N],d[N];int maxd,pos;int rt[N],dm[N];inline void dfs(int u,int fa,int z){ depth[u]=depth[fa]+1; rt[u]=z; if (depth[u]>maxd) maxd=depth[pos=u]; d[u]=max(d[u],depth[u]-1); for (int p=head[u];p;p=G[p].next) if (V!=fa) dfs(V,u,z);}vector<ll> cnt[N],sum[N];inline ll Cnt(int x,int y){ if (y>=cnt[x].size()) return 0; return cnt[x][y];}inline ll Sum(int x,int y){ if (y>=sum[x].size()) return 0; return sum[x][y];}vector<int> ab[N];inline void count(int u,int fa,int z){ cnt[z][d[u]]++; sum[z][d[u]]+=d[u]; ab[z].pb(u); for (int p=head[u];p;p=G[p].next) if (V!=fa) count(V,u,z);}int n,m,Q;vector<abcd> que;double ans[N];map<abcd,double> Map;int main(){ int x,y; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); read(Q); for (int i=1;i<=m;i++) read(x),read(y),add(x,y,++inum),add(y,x,++inum); for (int i=1;i<=n;i++) if (!depth[i]){ maxd=0,pos=0; dfs(i,0,i); int t=pos; maxd=0,pos=0; dfs(t,0,i); dm[i]=maxd-1; t=pos; maxd=0,pos=0; dfs(t,0,i); cnt[i].resize(maxd),sum[i].resize(maxd); count(i,0,i); for (int j=maxd-2;j>=0;j--) cnt[i][j]+=cnt[i][j+1],sum[i][j]+=sum[i][j+1]; } for (int i=1;i<=Q;i++){ read(x); read(y); x=rt[x]; y=rt[y]; if (x==y) { printf("-1\n"); continue; } if (ab[x].size()>ab[y].size() || (ab[x].size()==ab[y].size() && x>y)) swap(x,y); if (Map.count(abcd(x,y))) { printf("%.10lf\n",Map[abcd(x,y)]); continue; } ll ans=0,dd=max(dm[x],dm[y]); for (int u:ab[x]) ans+=Cnt(y,dd-d[u])*(1+d[u])+Sum(y,dd-d[u])+(ab[y].size()-Cnt(y,dd-d[u]))*dd; printf("%.10lf\n",Map[abcd(x,y)]=(double)ans/ab[x].size()/ab[y].size()); } return 0;}