【题解】[Codeforces 1067E] Random Forest Rank【结论题 概率DP】

题目链接

题意

给定一棵树,每条边有 \(\dfrac{1}{2}\) 的概率出现,求该森林邻接矩阵的轶的期望。\(n\leq 5\times 10^5\)

题解

结论:轶为最大匹配的两倍。

秩相当于选一个最大的满秩的子矩阵。考虑子矩阵的行列式,一个有贡献的排列相当于找若干条有向边,使得每个点入度出度最大等于 1.
这个东西相当于最大匹配。因为这是一棵树,这个东西是唯一的,行列式的值不会被抵消掉
所以这个邻接矩阵的秩等于最大匹配。

于是 DP 每个点与其儿子匹配的概率。

#include<bits/stdc++.h>
using namespace std;
int getint(){
    int ans=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        ans=ans*10+c-'0';
        c=getchar();
    }
    return ans*f;
}
const int N=5e5+10,mod=998244353,inv2=(mod+1)/2;
struct bian{
    int e,n;
};
bian b[N<<1];
int s[N],tot=0;
void add(int x,int y){
    tot++;
    b[tot].e=y;
    b[tot].n=s[x];
    s[x]=tot;
}

int f[N];
void ss(int x,int fa){
    f[x]=1;
    for(int i=s[x];i;i=b[i].n){
        int v=b[i].e;
        if(v==fa)continue;
        ss(v,x);
        f[x]=f[x]*(f[v]+1ll)%mod*inv2%mod;
    }
    f[x]=(mod+1-f[x])%mod;
}

int main(){
    int n=getint(),p2=1;
    for(int i=0;i<n-1;i++){
        int x=getint(),y=getint();
        add(x,y);
        add(y,x);
        p2<<=1;
        p2>=mod&&(p2-=mod);
    }
    ss(1,0);
    long long s=0;
    for(int i=1;i<=n;i++)s+=f[i];
    cout<<s%mod*2*p2%mod;
    return 0;
}

posted @ 2020-12-31 17:15  破壁人五号  阅读(99)  评论(0编辑  收藏  举报