luogu-P3343题解

简要题意

给定一张 n 个点 m 条边的图,边的边权是 [0,1] 之间均匀分布的随机实数,且相互独立。求最小生成树的最大边权的期望值。

思路

首先有一个比较神秘的跟概率有关的东西,虽然题面中已经给出提示,但这里还是进行简单说明:

引理:将长度为 n 的区间随机划成 m 段,每段长度期望是 nm

笔者询问 deepseek,deepseek 给出了三种证明方法,在此仅给出笔者知道的一种。

我们设第 i 段长度为 Li,就有:n=i=1mLi

根据期望的线性性和对称性我们可以得到:n=E(i=1mLi)=i=1mE(Li)L1=L2==Lm

所以 E(Li)=nm

所以第 k 大的边贡献就是 km+1。我们首先能够有一个 naive 的想法,枚举每个边的大小关系,然后暴力跑 kruskal。这个想法可以启发我们去思考如何统计所有第 k 大的边的贡献。

首先看每种情况做贡献的概率,确定了选择哪些边要选和哪个边做贡献后就好做了,有 P=(k1)!(mk)!m!。因为期望等于总方案数除以概率,所以现在我们只需要去找方案数,这个就 dp 去求。

因为恰好选第 k 大的边使图连通不好描述,所以容斥,变成选第 k 大的边前图不连通的方案数减去选第 k 大的边后图不连通的方案数。于是就有一个 dp,设 fS,i 表示 S 构成的点集中选 i 条边图不连通的方案,现在考虑枚举子集进行转移。转移就从若干已经连通的子图中选出剩下的一些边,但是不能使整个图连通,所以从严格意义上说是枚举真子集。所以引入 gS,i 表示 S 构成的点集中选 i 条边图连通的方案,就有下面两个转移式:

gS,i=(dSi)fS,i

fS,i=TSjdTgT,j(dS/Tij)

其中 dSS 的导出子图。

最后的答案就是:

1m+1imi(fU,i1(dUi1)fU,i(dUi))

化简得:

1m+1imfU,i(dUi)

代码

signed main(){
    n = rd(), m = rd();
    for(int i = 1, u, v; i <= m; ++i)u = rd(), v = rd(), ++mp[(1 << u - 1) | (1 << v - 1)];
    for(int S = 1; S < (1 << n); ++S)for(int T = S; T; T = T - 1 & S)d[S] += mp[T];
    c[0][0] = c[1][0] = 1;
    for(int i = 1; i <= m; c[++i][0] = 1)for(int j = 1; j <= i; ++j)c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
    for(int S = 1; S < (1 << n); ++S)for(int i = 0; i <= d[S]; ++i){
        for(int T = S & S - 1; T; T = T - 1 & S)if(T & (S & - S))
            for(int j = 0; j <= min(i, d[T]); ++j)f[S][i] += g[T][j] * c[d[S ^ T]][i - j];
        g[S][i] = 1.0 * c[d[S]][i] - f[S][i];
    }
    for(int i = 0; i <= m; ++i)ans += f[(1 << n) - 1][i] / c[m][i];
    ans /= 1.0 + m;
    printf("%.6f", ans);
    return 0;
}
posted @   Lyrella  阅读(5)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示