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); }