新萌妹子刚学 OI 0s (WA on 27求调教
查看原帖
新萌妹子刚学 OI 0s (WA on 27求调教
684245
zhangyaiwei楼主2024/10/16 11:09
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a,b,dep[111111],s[111111]/*子树大小*/,f[111111][21]/*倍增求LCA*/,f1[111111]/*子树深度和*/,f2[111111]/*整树距离和*/;
vector<int> v[111111];
void dfs1(int x,int deep){
	dep[x]=deep,s[x]=1;
	for(int i=0;i<v[x].size();i++){
		int N=v[x][i];
		if(N==f[x][0]) continue;
		f[N][0]=x,dfs1(N,deep+1);
		f1[x]+=s[N]+f1[N];
		s[x]+=s[N];
	}
}
void dfs2(int x){
	for(int i=0;i<v[x].size();i++){
		int N=v[x][i];
		if(N==f[x][0]) continue;
		f2[N]=f2[x]+n-2*s[N],dfs2(N);
	}
}
int LCA(int a,int b){
	if(dep[a]!=dep[b]){
		for(int i=20;i>=0;i--){
			if(dep[f[a][i]]>dep[b]) a=f[a][i];
		}
		a=f[a][0];
	}
	if(a!=b){
		for(int i=20;i>=0;i--){
			if(f[a][i]!=f[b][i]) a=f[a][i],b=f[a][i];
		}
		a=f[a][0],b=f[b][0];
	}
	return a;
}
int GET(int a,int b){//求a在b的哪个儿子的子树里
	for(int i=20;i>=0;i--){
		if(dep[f[a][i]]>dep[b]) a=f[a][i];
	}
	return a;
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<n;i++){
		cin>>a>>b;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	dfs1(1,1);
	f2[1]=f1[1];
	dfs2(1);
	f[1][0]=1;
	for(int i=1;i<20;i++){
		for(int j=1;j<=n;j++){
			f[j][i]=f[f[j][i-1]][i-1];
		}
	}
    // for(int i=1;i<=n;i++){
    //     cout<<f1[i]<<" "<<f2[i]<<" "<<s[i]<<" "<<dep[i]<<endl;
    // }
	while(m--){
		cin>>a>>b;
		if(dep[a]<dep[b]) swap(a,b);
		int Lca=LCA(a,b);
		//cout<<Lca<<endl;
		if(Lca==b){
			int Get=GET(a,b);
			//cout<<Get<<" "<<Lca<<endl;
			printf("%.10f\n",double(f2[b]-f1[Get]-s[Get]/*去除包含a的子树*/)/(n-s[Get])+double(f1[a])/s[a]+dep[a]-dep[b]+1/*必会选到的部分*/);
		}
		else{
			printf("%.10f\n",double(f1[a])/s[a]+double(f1[b])/s[b]+dep[a]+dep[b]-2*dep[Lca]+1/*必会选到的部分*/);
		}
	}
}

很玄学的是,只有整数部分错了,小数部分没错 链接

2024/10/16 11:09
加载中...