CF280C Game on Tree(期望)

版权声明:未经本蒟蒻同意,请勿转载本蒻博客 https://blog.csdn.net/wddwjlss/article/details/80624217

题意:给出一颗含n个白点的有根树,每次随机选择一个还没有被染黑的点,将这个点和这个点子树中所有的点染黑,问期望操作多少次后所有点都被染黑。n<=100000。

看上去无从下手QwQ
其实实现起来非常简单,但是思维难度很大,作为一个蒟蒻,当然是听别人讲完之后才AC的。

我们单独考虑一个节点有多大概率被选到,概率是所有祖先被染的概率加上自己的概率。每一个点的到根的所有点中自己先被选到的概率是 1 d e p [ x ] ,先选到才会产生代价。所以答案是 i = 1 n 1 d e p [ i ] ,因为只有先被选到才会对总次数产生贡献。

鸣谢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;
}

猜你喜欢

转载自blog.csdn.net/wddwjlss/article/details/80624217