BZOJ 3925 [Zjoi2015]地震后的幻想乡 ——期望DP

我们只需要考虑$\sum F(x)P(x)$的和,

$F(x)$表示第x大边的期望,$P(x)$表示最大为x的概率。

经过一番化简得到$ans=\frac{\sum T(x-1)}{m+1}$

所以就是考虑x条边不能构成生成树的概率,我们用总方案除以所有情况即可。

然后DP就好了。

#include <map>
#include <ctime>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
 
int e[1<<12],n,m,d[1<<12],s[1<<12];
ll c[50][50],f[1<<12][50],g[1<<12][50];
 
void print(int x)
{
    F(i,0,n-1) printf("%d",(x>>i)&1);
//  printf("\n");
}
 
int main()
{
    scanf("%d%d",&n,&m);
    F(i,1,m)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        a--;b--;
        e[a]|=1<<b; e[b]|=1<<a;
    }
    F(i,0,m)
    {
        c[i][0]=c[i][i]=1;
        F(j,1,i-1)
            c[i][j]=c[i-1][j]+c[i-1][j-1];
    }
    F(i,0,(1<<n)-1) s[i]=s[i>>1]+(i&1);
    F(i,0,(1<<n)-1)
    {
        F(j,0,n-1) if ((i>>j)&1) d[i]+=s[e[j]&i];
        d[i]>>=1;
    }
    F(i,0,(1<<n)-1)
        if (s[i]==1) g[i][0]=1;
        else
        {
            int t=i&-i;
            for (int j=(i-1)&i;j;j=(j-1)&i)
                if (j&t)
                    F(a,0,d[j]) F(b,0,d[i^j])
                        f[i][a+b]+=g[j][a]*c[d[i^j]][b];
            F(j,0,d[i]) g[i][j]=c[d[i]][j]-f[i][j];
        }
    double ans=0.0;
    F(i,0,m-1) ans+=1.0*f[(1<<n)-1][i]/c[m][i];
    ans/=1.0*(m+1);
    printf("%.6f\n",ans);
}

  

posted @ 2017-04-05 17:58  SfailSth  阅读(176)  评论(0编辑  收藏  举报