BZOJ 3925 [Zjoi2015]地震后的幻想乡
2015-08-19 23:49
309 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3925
题意:给定一个nn点mm边的无向图,没有重边和自环,每条边的权值为[0,1][0,1]之间的随机变量,求最小生成树中最大边的期望权值。
n≤10,m≤n(n−1)2n\le10,m\le\frac{n(n-1)}{2}。
题解:根据期望的线性性,我们可以算出随机选前kk小的那些边使图恰好连通的概率,则答案为概率之和除以(m+1)(m+1),因为对于mm个[0,1][0,1]之间的随机变量x1,x2,...,xmx_1,x_2,...,x_m,第kk小的那个的期望值是km+1\frac{k}{m+1}。
此题略卡精度,所以我们可以考虑先算出可行方案数,再除以总方案数得到概率。
令cnt[i]cnt[i]表示点集ii之间的无向边边数,f[i][j]f[i][j]表示点集为ii,选用jj条边使点集不连通的方案数,g[i][j]g[i][j]表示点集为ii,选用jj条边使点集连通的方案数,那么显然有f[i][j]+g[i][j]=(jcnt[i])f[i][j] + g[i][j] = \binom{j}{cnt[i]},而计算ff的方法,可以是通过枚举包含点集里某个定点的连通块大小来不重不漏的计数。
对于计算f[S]f[S],考虑包含点集SS中某个定点PP的点集TT,则TT为SS的真子集且TT和S−TS-T之间没有连边,就可以不重不漏地代表SS不连通的所有情况,但是两个子点集的边数任意,只用保证TT是连通的,那么就有f[S][i+j]=∑T⊂Sg[T][i]∗(jcnt[S−T])f[S][i+j]=\sum_{T\subset S}{g[T][i]*\binom{j}{cnt[S-T]}}
这个转移可以通过对子集的枚举做到O(3nm)O(3^nm)。
令全集为allall,于是答案为1m+1∑i=0mf[all][i](icnt[all])\frac{1}{m+1}\sum_{i=0}^{m}\frac{f[all][i]}{\binom{i}{cnt[all]}}
这样做用
代码:
题意:给定一个nn点mm边的无向图,没有重边和自环,每条边的权值为[0,1][0,1]之间的随机变量,求最小生成树中最大边的期望权值。
n≤10,m≤n(n−1)2n\le10,m\le\frac{n(n-1)}{2}。
题解:根据期望的线性性,我们可以算出随机选前kk小的那些边使图恰好连通的概率,则答案为概率之和除以(m+1)(m+1),因为对于mm个[0,1][0,1]之间的随机变量x1,x2,...,xmx_1,x_2,...,x_m,第kk小的那个的期望值是km+1\frac{k}{m+1}。
此题略卡精度,所以我们可以考虑先算出可行方案数,再除以总方案数得到概率。
令cnt[i]cnt[i]表示点集ii之间的无向边边数,f[i][j]f[i][j]表示点集为ii,选用jj条边使点集不连通的方案数,g[i][j]g[i][j]表示点集为ii,选用jj条边使点集连通的方案数,那么显然有f[i][j]+g[i][j]=(jcnt[i])f[i][j] + g[i][j] = \binom{j}{cnt[i]},而计算ff的方法,可以是通过枚举包含点集里某个定点的连通块大小来不重不漏的计数。
对于计算f[S]f[S],考虑包含点集SS中某个定点PP的点集TT,则TT为SS的真子集且TT和S−TS-T之间没有连边,就可以不重不漏地代表SS不连通的所有情况,但是两个子点集的边数任意,只用保证TT是连通的,那么就有f[S][i+j]=∑T⊂Sg[T][i]∗(jcnt[S−T])f[S][i+j]=\sum_{T\subset S}{g[T][i]*\binom{j}{cnt[S-T]}}
这个转移可以通过对子集的枚举做到O(3nm)O(3^nm)。
令全集为allall,于是答案为1m+1∑i=0mf[all][i](icnt[all])\frac{1}{m+1}\sum_{i=0}^{m}\frac{f[all][i]}{\binom{i}{cnt[all]}}
这样做用
double就可以保证精度了,无需
__float128。
代码:
[code]#include <cstdio> const int maxn = 11, maxm = 46; int n, m, e[maxn], sz[1 << maxn], cnt[1 << maxn]; long long c[maxm][maxm], f[1 << maxn][maxm], g[1 << maxn][maxm]; double ans; int main() { scanf("%d%d", &n, &m); for(int i = 0; i < m; ++i) { int u, v; scanf("%d%d", &u, &v); --u; --v; e[u] |= 1 << v; e[v] |= 1 << u; } c[0][0] = 1; for(int i = 1; i <= m; ++i) { c[i][0] = c[i][i] = 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) { sz[s] = sz[s >> 1] + (s & 1); if(sz[s] == 1) { g[s][0] = 1; continue; } for(int i = 0; i < n; ++i) if((s >> i) & 1) cnt[s] += sz[e[i] & s]; cnt[s] >>= 1; int lowbit = s & -s; for(int t = (s - 1) & s; t; t = (t - 1) & s) if(t & lowbit) for(int i = 0; i <= cnt[t]; ++i) for(int j = 0; j <= cnt[s ^ t]; ++j) f[s][i + j] += g[t][i] * c[cnt[s ^ t]][j]; for(int i = 0; i <= cnt[s]; ++i) g[s][i] = c[cnt[s]][i] - f[s][i]; } for(int i = 0; i <= m; ++i) ans += (double)f[(1 << n) - 1][i] / c[cnt[(1 << n) - 1]][i]; ans /= m + 1; printf("%.6f\n", ans); return 0; }
相关文章推荐
- 苹果开发 笔记(63)Masonry
- NDIS中间层驱动学习小记
- c# lambda distinct
- [CTCI] 最长合成字符串
- mysql-5.6.17-win32免安装版配置
- 二维数组的指针
- 1056. Mice and Rice (25)
- HD 1869 六度分离【dijkstra】
- hdoj 2553 N皇后问题
- 黑马程序员---学习笔记6:字符串
- struct2-json
- uva 11177 - Fighting Against a Polygonal Monster(几何)
- OC基础 -- 内存管理详解
- 进程通信
- zeromq中两个dealer 通过一个router进行通信
- Android 之使用LocalBroadcastManager解决BroadcastReceiver安全问题
- wxPython Cookbook(Chatper2)Part 1
- 好网址
- python yield 实例理解要点
- zoj 1610 Count the Colors 【区间覆盖 求染色段】