版权声明:未经本蒟蒻同意,请勿转载本蒻博客 https://blog.csdn.net/wddwjlss/article/details/80624217
题意:给出一颗含n个白点的有根树,每次随机选择一个还没有被染黑的点,将这个点和这个点子树中所有的点染黑,问期望操作多少次后所有点都被染黑。n<=100000。
看上去无从下手QwQ
其实实现起来非常简单,但是思维难度很大,作为一个蒟蒻,当然是听别人讲完之后才AC的。
我们单独考虑一个节点有多大概率被选到,概率是所有祖先被染的概率加上自己的概率。每一个点的到根的所有点中自己先被选到的概率是 ,先选到才会产生代价。所以答案是 ,因为只有先被选到才会对总次数产生贡献。
鸣谢forever_shi神犇给我讲解
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=200000;
struct node
{
int next,to;
}e[MAXN];
int head[MAXN],num,n;
double dep[MAXN];//注意是要开double
inline void add(int from,int to)
{
e[++num].next=head[from];
e[num].to=to;
head[from]=num;
}
void dfs(int x,int fa)
{
dep[x]=dep[fa]+1.0;
for(int i=head[x];i!=0;i=e[i].next)
{
int y=e[i].to;
if(y==fa)
continue;
dfs(y,x);
}
}
double ans;
int main()
{
cin>>n;
for(int i=1;i<=n-1;++i)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,0);
for(int i=1;i<=n;++i)
{
if(dep[i]!=0)//特判以下,保证不会有除0的情况(没有这个会gg)
ans+=1/dep[i];
}
printf("%.10lf",ans);
return 0;
}