注意到题目这个提示:
对于n个[0,1]之间的随机变量x1,x2,…,xn,第k小的那个的期望值是k/(n+1)。
这说明我们要求修复时间的期望,只要求出用排名<=k的边恰好能使原图连通的概率就好了
然后推一下柿子
P(i)是用排名<=i的边恰好能使原图连通的概率
P
(
i
)
是
用
排
名
<=
i
的
边
恰
好
能
使
原
图
连
通
的
概
率
Q(i)=∑mj=iP(j) Q ( i ) = ∑ j = i m P ( j )
L(i)是用<=i的边不能使原图连通的概率
L
(
i
)
是
用
<=
i
的
边
不
能
使
原
图
连
通
的
概
率
然后要求L(i),设 f[mask][i],g[mask][i] 表示用i条边使得点集mask 连通/不连通的方案数,做个 O(3nm2) O ( 3 n m 2 ) 的dp
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define lowbit(x) (x)&(-(x))
using namespace std;
const int maxn = 11;
const int maxm = 50;
int to[1<<maxn];
ll C[maxm][maxm];
int n,m,al;
int cnt[1<<maxn],v[maxn][maxn];
ll f[1<<maxn][maxm],g[1<<maxn][maxm];
// 不联通 联通
int main()
{
for(int i=0;i<maxn;i++) to[1<<i]=i;
C[0][0]=1;
for(int i=1;i<maxm;i++)
{
C[i][0]=1;
for(int j=1;j<=i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j];
}
scanf("%d%d",&n,&m); al=1<<n;
for(int i=1;i<=m;i++)
{
int x,y; scanf("%d%d",&x,&y);
v[x][y]=v[y][x]=1;
}
for(int i=1;i<al;i++)
{
int j=to[lowbit(i)]+1,ii=i^lowbit(i);
cnt[i]=cnt[ii];
for(int k=1;k<=n;k++) if(ii>>k-1&1)
cnt[i]+=v[j][k];
}
g[0][0]=1;
for(int i=1;i<al;i++)
{
int k=to[lowbit(i)]+1;
for(int j=0;j<=cnt[i];j++)
{
for(int l=(i-1)&i;l;l=(l-1)&i) if(l>>k-1&1)
{
for(int z=0;z<=j&&z<=cnt[l];z++)
f[i][j]+=g[l][z]*C[cnt[i-l]][j-z];
}
g[i][j]=C[cnt[i]][j]-f[i][j];
}
}
double re=0.0;
for(int x=1;x<=m;x++)
re+=(double)f[al-1][x-1]/(double)C[cnt[al-1]][x-1];
re/=m+1;
printf("%.6lf\n",re);
return 0;
}