Description

【题目描述】

给出一个n个节点的树,两点之间有且仅有一条路径相连。

给出m个点对xi,yi,如果添加一条双向边边{u,v}后xi和yi在一个简单环中,则称这条边是happy的,happy值为这个简单环的点数。

请你求出对于点对xi,yi,所有happy的边的happy值的平均数。



注意,出题人似乎认为简单环是包括自环的。

【输入数据】

第一行2个整数n,m;

接下来n-1行,每行两个整数x,y表示在树中x,y有一条双向边相连;

接下来m行,每行2个整数xi,yi表示询问点对。

【输出数据】

对于每个询问的点对,输出一个实数表示所有happy的边的happy值的平均数,结果保留7位小数。

【样例输入1】

4 3

2 4

4 1

3 2

3 1

2 3

4 1

【样例输出1】

4.0000000

3.0000000

3.0000000

【样例输入2】

3 3

1 2

1 3

1 2

1 3

2 3

【样例输出2】

2.5000000

2.5000000

3.0000000

【样例解释】

在样例2中:对于第一个询问,边{1,2}和边{2,3}都是happy的,happy值分别为2,3,ans=(2+3)/2

对于第二个询问,边{1,3}和边{2,3}都是happy的,happy值分别为2,3,ans=(2+3)/2

对于第三个询问,只有边{2,3}是happy的,happy值为3,ans=3/1

【数据范围】

对于20%的数据满足:n<=100,m<=100;
对于100%的数据满足:n<=100000,m<=100000。

思路

单独考虑每个点对答案的贡献
统计一下子树内的
还有统计上面的

所以正着dfs一遍,倒着dfs一遍即可

代码

#include<bits/stdc++.h>
#define ll long long
#define N 100077
using namespace std;
ll n,m,fa[N][17],dep[N],ls[N],v[N<<1],nx[N<<1],cnt=0,siz[N],ans1[N],ans2[N];
double ans[N];
void add(ll s,ll e)
{
    cnt++;v[cnt]=e;nx[cnt]=ls[s];ls[s]=cnt;
    cnt++;v[cnt]=s;nx[cnt]=ls[e];ls[e]=cnt;
}
  
void dfs1(ll u,ll f)
{
    siz[u]=1;
    fa[u][0]=f;
    for(ll i=1; i<=16; i++)fa[u][i]=fa[fa[u][i-1]][i-1];
    for(ll i=ls[u]; i; i=nx[i])
        if(v[i]^f)
        {
            dep[v[i]]=dep[u]+1;
            dfs1(v[i],u);
            siz[u]+=siz[v[i]];
        }
}
void go_up(ll &k,ll d)
{
    for(ll i=16; i>=0;--i)
        if(d&(1<<i))k=fa[k][i];
}
ll LCA(ll a,ll b)
{
    if(dep[a]>dep[b])go_up(a,dep[a]-dep[b]);
    if(dep[a]<dep[b])go_up(b,dep[b]-dep[a]);
    if(a==b)return a;
    for(ll i=16; i>=0;--i)
        if(fa[a][i]!=fa[b][i])
        {
            a=fa[a][i];
            b=fa[b][i];
        }
    return fa[a][0];
}
  
void dfs2(ll u,ll f)
{
    ans1[u]=dep[u];
    for(ll i=ls[u]; i; i=nx[i])
       if(v[i]^f)
       {
            ans2[v[i]]=ans2[u]-siz[v[i]]+(n-siz[v[i]]);
            dfs2(v[i],u);
            ans1[u]+=ans1[v[i]];
       }
}
  
void dfs3(ll u,ll f)
{
    ll sum1=1,sum2=0;
    for(ll i=ls[u]; i; i=nx[i])
        if(v[i]^f)
        {
            sum1+=1ll*siz[v[i]]*(n-siz[v[i]]);
            sum2+=(ans1[v[i]]-1ll*siz[v[i]]*dep[u])*(n-siz[v[i]]);
        }
    if(f)
    {
        sum1+=1ll*(n-siz[u])*siz[u];
        sum2+=(ans2[u]-(ans1[u]-1ll*dep[u]*siz[u]))*siz[u];
    }
    sum1+=n;
    sum1/=2;
    ans[u]=1.0*sum2/sum1+1.0;
    for(ll i=ls[u]; i; i=nx[i])
        if(v[i]^f)
            dfs3(v[i],u);
}
  
  
int main()
{
    scanf("%lld%lld",&n,&m);
    ll s,e;
    for(ll i=1; i<n; i++)
    {
        scanf("%lld%lld",&s,&e);
        add(s,e);
    }
    dfs1(1,0);
    for(ll i=1; i<=n; i++)ans2[1]+=dep[i];
    dfs2(1,0);
    dfs3(1,0);
    ll x,y;
    for(ll i=1; i<=m; i++)
    {
        scanf("%lld%lld",&x,&y);
        if(x==y)printf("%.7lf\n",ans[x]);
        else
        {
            ll lca=LCA(x,y);
            ll sum1=0,sum2=0;
            if(x==lca||y==lca)
            {
                if(x!=lca)swap(x,y);
                ll d=y;
                go_up(d,dep[y]-dep[x]-1);
                sum1=1ll*(n-siz[d])*siz[y];
                sum2+=1ll*(ans1[y]-1ll*siz[y]*dep[y])*(n-siz[d]);
                sum2+=(ans2[x]-(ans1[d]-1ll*siz[d]*dep[x]))*siz[y];
                double res=1.0*sum2/sum1;
                res+=1.0;
                res+=dep[y]-dep[x];
                printf("%.7lf\n",res);
            }
            else
            {
                sum1=1ll*siz[x]*siz[y];
                sum2+=(ans1[x]-1ll*siz[x]*dep[x])*siz[y];
                sum2+=(ans1[y]-1ll*siz[y]*dep[y])*siz[x];
                double res=1.0*sum2/sum1;
                res+=1.0;
                res+=dep[x]+dep[y]-2*dep[lca];
                printf("%.7lf\n",res);
            }
        }
    }
}