Codeforces-629E Famil Door and Roads(期望)
阿新 • • 發佈:2018-11-06
題意
給定一棵
個節點的樹,
個詢問,每一個詢問包含兩個引數
,我們能夠通過加一條邊使
處於同一個環內。對於每一個詢問,求這樣的環的期望長度。
思路
細節比較多的一道題。首先我們可以用期望的線性性質,把環的期望拆成多個值,假設邊連線
,形成
這樣的環。那麼
。
不難發現,需要分類討論,分
有無祖宗關係。
假如沒有祖宗關係,那
只能分別在
的子樹中出現,我們可以維護一個
陣列,
表示
的子節點到
的距離總和。
而若有祖宗關係,假設
節點更深,那麼仍有
,而
則可以選擇除
(設它為
) 這棵子樹外的所有節點,那我們方便起見,可以先預處理一個節點到其它所有節點的距離之和
。
只用將
減去
, 即
到子樹
中節點的距離總和,再除以
即可。
程式碼
#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;
}