[ZJOI2015] 地震後的幻想鄉

LUHCUH發表於2024-06-27

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

相關文章