版权声明:我这种蒟蒻的文章,真正的大佬一般看不上的_(:з」∠)_ https://blog.csdn.net/Paulliant/article/details/82711029
题意
给定一棵
个节点的树,
个询问,每一个询问包含两个参数
,我们能够通过加一条边使
处于同一个环内。对于每一个询问,求这样的环的期望长度。
思路
细节比较多的一道题。首先我们可以用期望的线性性质,把环的期望拆成多个值,假设边连接
,形成
这样的环。那么
。
不难发现,需要分类讨论,分
有无祖宗关系。
假如没有祖宗关系,那
只能分别在
的子树中出现,我们可以维护一个
数组,
表示
的子节点到
的距离总和。
而若有祖宗关系,假设
节点更深,那么仍有
,而
则可以选择除
(设它为
) 这棵子树外的所有节点,那我们方便起见,可以先预处理一个节点到其它所有节点的距离之和
。
只用将
减去
, 即
到子树
中节点的距离总和,再除以
即可。
代码
#include<bits/stdc++.h>
#define FOR(i,x,y) for(register int i=(x);i<=(y);++i)
#define DOR(i,x,y) for(register int i=(x);i>=(y);--i)
#define N 100003
typedef long long LL;
using namespace std;
template<const int maxn,const int maxm>struct Linked_list
{
int head[maxn],to[maxm],nxt[maxm],tot;
void clear(){memset(head,-1,sizeof(head));tot=0;}
void add(int u,int v){to[++tot]=v,nxt[tot]=head[u],head[u]=tot;}
#define EOR(i,G,u) for(register int i=G.head[u];~i;i=G.nxt[i])
};
Linked_list<N,N<<1>G;
int dfn[N],dep[N],fa[N],sz[N],son[N],top[N],ori[N],ord;
LL sum1[N],sum2[N];
int n,m;
LL gcd(LL x,LL y){return y?gcd(y,x%y):x;}
void dfs(int u,int f,int d)
{
dep[u]=d,fa[u]=f,sz[u]=1,son[u]=0,sum1[u]=0;
EOR(i,G,u)
{
int v=G.to[i];
if(v==f)continue;
dfs(v,u,d+1);
sum1[u]+=sum1[v]+sz[v];
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
void make_path(int u,int f,int tp)
{
dfn[u]=++ord,ori[ord]=u,top[u]=tp;
if(son[u])make_path(son[u],u,tp);
EOR(i,G,u)
{
int v=G.to[i];
if(v==f||v==son[u])continue;
make_path(v,u,v);
}
}
int jmp(int x,int d)
{
while(dep[x]-dep[fa[top[x]]]<=d)
{
d-=dep[x]-dep[fa[top[x]]];
x=fa[top[x]];
}
return ori[dfn[x]-d];
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
else y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
void redfs(int u,int f,LL cur)
{
sum2[u]=cur;
EOR(i,G,u)
{
int v=G.to[i];
if(v==f)continue;
redfs(v,u,cur-sz[v]+(n-sz[v]));
}
}
int main()
{
G.clear();
scanf("%d%d",&n,&m);
FOR(i,1,n-1)
{
int u,v;
scanf("%d%d",&u,&v);
G.add(u,v),G.add(v,u);
}
dfs(1,0,1);
ord=0;make_path(1,0,1);
redfs(1,0,sum1[1]);
while(m--)
{
int x,y,z,lca;
LL p1,p2,q1,q2,p,q;
scanf("%d%d",&x,&y);
if(dep[x]<dep[y])swap(x,y);
lca=LCA(x,y);
p1=sum1[x],q1=sz[x];
if(lca==y)
{
z=jmp(x,dep[x]-dep[y]-1);
p2=sum2[y]-sum1[z]-sz[z],q2=n-sz[z];
}
else p2=sum1[y],q2=sz[y];
p=q1*q2*(dep[x]+dep[y]-2*dep[lca]+1)+p1*q2+p2*q1;
q=q1*q2;
printf("%lld/%lld\n",p/gcd(p,q),q/gcd(p,q));
}
return 0;
}