CF280C Game on tree(期望dp)

这道题算是真正意义上人生第一道期望的题?

题目大意:

给定一个n个点的,以1号点为根的树,每一次可以将一个点和它的子树全部染黑,求染黑所有点的期望

QwQ说实话,我对期望这种东西,一点也不理解。。。

根据期望的线性性,计算出每个点比选择的期望次数,然后直接相加

所以得出\(E(x) = \frac{1}{dep[x]}\)

这里之所以是$ \frac{1}{dep[x]}$是因为我们求的期望是每个点把自己及自己子树染黑的概率(而不是靠祖先)

或者换种说法:

整棵树的期望操作次数太大,难以找到方法。这时我们需要突破口。
该如何将大问题转化为小问题呢?我们发现,一棵树是可以分成好几颗子树的,而子树分解的最终状态就是所有的点。那么,我们是不是可以计算出 每个点被染黑的期望操作次数,然后相加就是整棵树的了?答案是当然可以。
这里需要注意的是,对于每个点的操作次数是指的在这个点上的操作。对于每一个点,如果其祖先被染黑了,它自己也会被顺带染黑,而这个对于该点来说是没有进行操作的。所以得出对于点x:\(E(x) = \frac{1}{dep[x]}\)

直接上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>

using namespace std;

inline int read()
{
  int x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

const int maxn = 1e5+1e2;
const int maxm = 2e5+1e2;

int point[maxn],nxt[maxm],to[maxm];
double dep[maxn];
int vis[maxn];
int n,m;
int cnt;

void addedge(int x,int y)
{
    nxt[++cnt]=point[x];
    to[cnt]=y;
    point[x]=cnt;
}

void dfs(int x,double dp)
{
    dep[x]=dp;
    vis[x]=1;
    for (int i=point[x];i;i=nxt[i])
    {
        int p = to[i];
        if (!vis[p])
        {
            dfs(p,dp+1.0);
        }
    }
}

double ans=0;

int main()
{
  scanf("%d",&n);
  for (int i=1;i<n;i++)
  {
    int x,y;
    x=read(),y=read();
    addedge(x,y);
    addedge(y,x);
  }
  //cout<<"gg"<<endl;
  dep[1]=1;
  dfs(1,1.0);
  for (int i=1;i<=n;i++)
  {
    ans=ans+1.0/dep[i]; 
  }
  printf("%.8lf",ans);
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/yimmortal/p/10160822.html
今日推荐