• CodeForces


    传送门: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?'
    ':' ');
            }
        }
        return 0;
    }

     

  • 相关阅读:
    在页面中控制媒体流的起播点和播放长度
    缓冲区数据转换为字符串输出
    编程中注意的一个问题
    一个整合SQL语句的类
    注意服务器系统日期对防病毒软件的影响
    网络病毒源的排查(2005年3月22日维护记录)
    升级到 Microsoft .NET >Visual Basic 6.0 控件和 .NET 控件的区别
    修改您的站点设计以改善下载体验
    下一版本Windows&reg; CE 开发工具Smart Device Extensions for Microsoft Visual Studio&reg; .NET
    WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/8584025.html
Copyright © 2020-2023  润新知