CodeForces - 697D - Puzzles DFS

Posted ckxkexing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 697D - Puzzles DFS相关的知识,希望对你有一定的参考价值。

传送门:D - Puzzles

题意:在一个图中,从1开始dfs,求每一个点到达的期望;

 

思路:(下面是队长写的)

首先求的是到每一个点的步数的期望.

记fa( u ) = v, son( v )表示v的儿子的集合,

z是son(v)中的点,其中 z != u ,  sum[z] 为 z 的子树的大小, p( z )表示z比u先访问到的概率;

那么可以发现对于u来说 ans[u] = ans[v] + 1 + x;

现在我要来算这个x, 如果 son(v).size == 1, 那么x为0;

否则能对u造成影响的就是son(v)中不是u的那些点,

以z为例, 如果z先于u访问到,那么到达u的步数就会加上sum[z], 那么 x += sum[z] * p(z);          

可以发现这样一个规律对于son(v)任意一种排列a,都可以发现一种对应排列b,满足a和b中只有u和z的位置对换.而且u和v不可能同时被访问或者其中一个不被访问,那么可以得到p(z) = 0.5; 就是 x += sum[z] * 0.5;

那么x就可以算出来了: for(auto it : son[v]) x += sum[it] * 0.5;

时间复杂度O(n);

所以下面的ac代码中,dfs1()就是求每一个点的sum值,通过类似前缀和的思想;

          get1()就是求ans;

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;

const int maxn = 100007;

int n,sum[maxn];
vector<int>mp[maxn];
double ans[maxn];
void init(){
    for(int i=1;i<=n;i++)
        mp[i].clear();
    memset(ans,0,sizeof(ans));
    memset(sum,0,sizeof(sum));
}
void dfs1(int d)
{
    sum[d] = 1;
    for(int  t=0; t < mp[d].size(); t++)
    {
        int to = mp[d][t];
        dfs1(to);
        sum[d] += sum[to];
    }
} 
void get1(int d)
{
    for(int t=0; t<mp[d].size(); t++)
    {
        int to = mp[d][t];
        ans[to] = ans[d] + 1 + (sum[d]-sum[to]-1) * 0.5;
        get1(to);
    }
}
int main(){
  //  freopen("in","r",stdin);
    while(~scanf("%d", &n))        
    {
        init();
        for(int i=2; i<=n; i++)
        {
            int x;
            scanf("%d",&x);
            mp[x].push_back(i);
        }
        dfs1(1);
        ans[1] = 1.0;
        get1(1);
        for(int i=1; i<=n; i++)
        {
            printf("%.1f%c", ans[i], i==n?\n: );
        }
    }
    return 0;
}

 

 

以上是关于CodeForces - 697D - Puzzles DFS的主要内容,如果未能解决你的问题,请参考以下文章

[补档计划] 动态规划3 - 树形DP

codeforces上怎么看测试数据

如何看codeforces做了多少题

codeforces上怎么看测试数据

codeforces比赛后怎么看题解和答案

codeforces是啥?