这个只要知道两个子树连在一起的直径端点必然是各自直径的端点就好了
然后瞎枚举一通
只要知道
∑i∑jmin{sizei,sizej},∑isizei=n
是
O(nn√)
的就好了
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#define pb push_back
using 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].v
int 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;
}