[ZJOI2015] 地震后的幻想乡

[ZJOI2015] 地震后的幻想乡

  • 首先考了选择前 \(k\) 小的边,恰好使得联通的概率 \(p_k\)
  • 此时的期望边权为 \(\frac{k}{m+1}\),其实就是第 \(k\)
  • \(p_k=\frac{g_k}{\binom{m}{k}}\),至于 \(g_k\) 怎么求
  • 可以考虑 \(g_{s,i}\),其中 \(s\) 为点集的状压的值,表示 \(i\) 个边使得点集 \(s\) 里的点联通的方案数
  • \(f_{s,i}\) 表示点集 \(s\) 不联通的方案数,\(h_s\) 表示原图上点集 \(s\) 两两连边的边数
    • \(g_{s,i}=\binom{h_s}{i}-f_{s,i}\)
    • \(f_{s,i}=\sum_{k\in t\subsetneqq s}g_{t,j}\binom{h_{s-t}}{i-j}\)\(k\) 是我们钦定的一个数在 \(s\)​ 中的一个点,枚举它所在的联通块,其他的随便选即可
  • 恰好联通不好计算,但是其等价于,没删这条边之前联通 减 删后不联通的方案数
  • \(Ans=\sum p_k\frac{k}{m+1}=\sum(\frac{f_{u,k-1}}{\binom{m}{k-1}}-\frac{f_{u,k}}{\binom{m}{k}})\frac{k}{(m+1)}=\frac{1}{m+1}\sum_{k=1}^m\frac{f_{u,k}}{\binom{h_{u}}{k}}\),其中 \(u\) 为全集
#include <bits/stdc++.h>
using namespace std;
inline int id(int x){x--;return 1<<x;}template<class ...T>inline int id(int x,T...t){return id(x)|id(t...);}
const int N=10,M=1<<N,K=51;
int n,m,cnt[M],sum[M]; double f[M][K],g[M][K],c[K][K];
int main()
{
    cin>>n>>m; int u,v,nn=1<<n;
    for(int i=1;i<=m;i++)
    cin>>u>>v,cnt[id(u,v)]++;
    for(int s=0;s<nn;s++)
        for(int t=s;t;t=s&t-1)
        sum[s]+=cnt[t];
    c[0][0]=1;
    for(int i=1;i<K;i++)
    {
        c[i][0]=c[i][i]=1;
        for(int j=1;j<i;j++)
            c[i][j]=c[i-1][j]+c[i-1][j-1];
    }
    for(int s=1;s<nn;s++)for(int i=0;i<=sum[s];i++)
    {
        for(int t=s;t;t=s&t-1)for(int j=0;j<=min(i,sum[s-t]);j++)
            if((s-t)&(s&-s))f[s][i]+=g[s-t][j]*c[sum[t]][i-j];
        g[s][i]=c[sum[s]][i]-f[s][i];
    }
    double ans=0;
    for(int i=0;i<=m;i++)ans+=f[nn-1][i]/c[m][i];
    ans/=m+1;printf("%.6lf\n",ans);
    return 0;
}
posted @ 2024-06-27 23:07  LUHCUH  阅读(22)  评论(0)    收藏  举报