题意翻译
给一片森林,(q)个询问,每个询问两个点,问将这两个点所在的集合连接起来组成的新集合,它的最远两点的距离的期望值是多少。
調了2個小時,終於好啦
求出每個聯通快直徑的兩端點
預處理每個點到最遠的點的距離
排序,前綴和,快速計算
#include<map>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
#define int long long
#define db double
inline int read(){
int x=0; char c=getchar();
while(c<'0'||c>'9')c=getchar();
while('0'<=c&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); }
return x;
}
int nxt[N<<1],head[N],go[N<<1],tot;
inline void add(int u,int v){
nxt[++tot]=head[u],head[u]=tot,go[tot]=v;
nxt[++tot]=head[v],head[v]=tot,go[tot]=u;
}
int n,m,q;
bool vis[N];
int dfn[N],low[N],co[N],st[N],si[N],top,col,num;
void Tarjan(int u){
st[++top]=u;
dfn[u]=low[u]=++num;
for(int i=head[u];i;i=nxt[i]){
int v=go[i];
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(!co[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
co[u]=++col;
si[col]=1;
while(st[top]!=u){
co[st[top]]=col;
si[col]++;
--top;
}
--top;
}
}
int dis[N],all[N],coin[N],p,Max;
void dfs(int u,int fa){
if(dis[u]>Max)Max=dis[u],p=u;
all[u]=max(all[u],dis[u]);
for(int i=head[u];i;i=nxt[i]){
int v=go[i];
if(v==fa)continue;
dis[v]=dis[u]+1;
dfs(v,u);
}
}
inline void findp(int u){
p=Max=-1; dfs(u,u); coin[co[u]]=max(coin[co[u]],Max);
Max=-1; dis[p]=0; dfs(p,p); coin[co[u]]=max(coin[co[u]],Max);
Max=-1; dis[p]=0; dfs(p,p); coin[co[u]]=max(coin[co[u]],Max);
}
vector<int>belong[N],Sum[N],e[N];
map<pair<int,int>,db>IF;
signed main(){
n=read(),m=read(),q=read();
for(int i=1;i<=m;i++)add(read(),read());
for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i);
for(int i=1;i<=n;i++){
if(!vis[co[i]])findp(i),vis[co[i]]=1;
belong[co[i]].push_back(i);
}
for(int i=1;i<=col;i++){
for(int j=0;j<belong[i].size();j++)e[i].push_back(all[belong[i][j]]);
sort(e[i].begin(),e[i].end());
for(int j=0;j<belong[i].size();j++){
Sum[i].push_back(e[i][j]);
if(j)Sum[i][j]+=Sum[i][j-1];
}
}
while(q--){
int a=co[read()],b=co[read()];
if(a==b){ printf("-1
"); continue;}
if(IF[make_pair(a,b)]>0)
{ printf("%.9f
",IF[make_pair(a,b)]); continue; }
if(si[a]>si[b])swap(a,b);
int ans=0,op=belong[a].size()*belong[b].size();
int MAXN=max(coin[a],coin[b]);
for(int i=0;i<e[a].size();i++){
int A=e[a][i]+1;
int mzx=upper_bound(e[b].begin(),e[b].end(),MAXN-A)-e[b].begin();
ans+=MAXN*mzx;
if(mzx==0)ans+=A*e[b].size()+Sum[b][Sum[b].size()-1];
else ans+=A*(e[b].size()-mzx)+Sum[b][Sum[b].size()-1]-Sum[b][mzx-1];
}
db res=(db)ans/op;
IF[make_pair(b,a)]=IF[make_pair(a,b)]=res;
printf("%.10f
",res);
}
}