• [Codeforces 1060F] Shrinking Tree


    Link:

    传送门

    Solution:

    原来CF的官方题解也能鸽啊……

    详细题解

    该题思路:

    1、对于每个点删边方案数为$fac[n-1]$,总贡献为每种方案下满足的概率的和,接下来直接求贡献

    2、每次将该点看成根,树形$dp$,设$dp[i][j]$表示根到$i$该子树还有$j$条边的贡献

    3、考虑合并子树(算上根到子树的边),由于两边互不影响,相乘后再乘上删边顺序不同的组合数皆可

    $dp[v1][i]*dp[v2][j]*C(i+j,i)*C((sz[v1]-1-i)+(sz[v2]-1-j),sz[v1]-1-i)$

    4、考虑用子树答案$dp[i]$算出加上子树根到其父亲的边后$cur[j]$的答案

    $j>i$时为了不重复计算,变数只有最后$u,v$的合并,产生的贡献为$0.5*dp[i]$

    $j=i$时考虑$u,v$合并和$sz[v]-1-i$条边的删除顺序任意,产生贡献为$(sz[v]-i)*dp[i]$

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=55;
    struct edge{int nxt,to;}e[MAXN<<2];
    int n,x,y,head[MAXN],sz[MAXN],tot;
    db cur[MAXN],tmp[MAXN],dp[MAXN][MAXN],fac[MAXN];
    
    void add(int x,int y)
    {e[++tot]=(edge){head[x],y};head[x]=tot;}
    db C(int x,int y)
    {return fac[x]/(fac[x-y]*fac[y]);}
    db solve(int x,int y)
    {return C(x+y,x);}
    void dfs(int x,int anc)
    {
        sz[x]=1;dp[x][0]=1;
        for(int i=head[x];i;i=e[i].nxt)
            if(e[i].to!=anc)
            {
                dfs(e[i].to,x);
                memset(cur,0,sizeof(cur));
                memset(tmp,0,sizeof(tmp));
                for(int j=0;j<=sz[e[i].to];j++)
                {
                    for(int k=0;k<j;k++)
                        cur[j]+=0.5*dp[e[i].to][k];
                    cur[j]+=(sz[e[i].to]-j)*dp[e[i].to][j];
                }
                
                for(int j=0;j<sz[x];j++)
                    for(int k=0;k<=sz[e[i].to];k++)
                        tmp[j+k]+=dp[x][j]*cur[k]*solve(j,k)*solve(sz[e[i].to]-k,sz[x]-1-j);
                for(int j=0;j<sz[x]+sz[e[i].to];j++) dp[x][j]=tmp[j];
                sz[x]+=sz[e[i].to];
            }
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
            scanf("%d%d",&x,&y),add(x,y),add(y,x);
        fac[0]=1;
        for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i;
        for(int i=1;i<=n;i++)
            dfs(i,0),printf("%.10lf
    ",dp[i][n-1]/fac[n-1]);
        return 0;
    }
  • 相关阅读:
    install source mysql 5.7.9
    直接复制php的安装目录部署到其他服务器的时候,无法运行
    对硬盘进行分区时,GPT和MBR有什么区别?
    centos添加永久静态路由
    Windows2008R2安装远程桌面终端授权
    nginx搭建的cdn服务器的nginx.conf配置文件
    centos6.6配置vlan三层交换
    ESXI 6.0 嵌套虚拟化 Hyper-v
    VLAN的Hybrid和Trunk端口有何区别
    如何添加使用博客RSS订阅
  • 原文地址:https://www.cnblogs.com/newera/p/9754936.html
Copyright © 2020-2023  润新知