题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3925

题意概述:

给出一张N点M边的最小生成树,其中每条边的长度为[0,1]的实数,求最小生成树中最大边的期望大小是多少。
N<=10,M<=N(N-1)/2.

由于本人实在太弱所以细节会描述的比较多。(精简版本见下方)

整理一下手里有的信息:

1.题目告诉我们N个大小在[0,1]的随机变量中第i大的期望大小为i/(N+1)。

2.由于两个[0,1]的随机变量大小相同的概率为0(小到为0),所以说只考虑每个随机变量大小不同的情况就可以了。

3.在所有边不同的条件下,在做最小生成树的时候第k条考察的边就是所有边中第k小的边(kruskal算法)。

所以如果知道图中最后一条加入最小生成树的边为所有边中第i大的概率p[i],那么答案就可以表示为:

ans=sum{ p[i] * i/(M+1) | 1<=i<=M }

根据信息3,可以发现p[i]实际上也就是第i条考察的边加入后恰好使得图连通的概率(注意i不是按照给出的边的顺序来考察的)。这又转化为了一个图的连通性问题,只要我们知道一个图中选择i条边使得图连通的概率xi,那么p[i]=xi-xi-1就是在第i条边加入之后图恰好连通的概率(因为i-1->i有两种可能,i-1就是连通的或者i-1是不连通的,所以是减法)。
好像某人说过“概率说到底还是一个组合计数问题”(离散概率),我们把这个概率xi用方案数来表示(注意到M<=45所以用C估计一下算出来的方案数的范围,并没有毛病)。设g(i)表示用i条边将图连通的方案数,则xi=g(i)/C(M,i)。(i条边使图连通的概率=i条边令图连通的方案数/选出i条边的方案数)

于是ans=sum{ (g(i)/C(M,i) - g(i-1)/C(M,i-1)) * i/(M+1) | 1<=i<=M }

接下来求出g问题就解决了。我们设g(s,i)表示用i条边将点集s中的点连通的方案数,那么f(s,i)表示用i条边不能将点集s中的点连通的方案数,有g(s,i)=C(cnt[s],i)-f(s,i),cnt[x]表示两端都在点集x中的边的条数。对于每个f(s,i)任意选择s中的一个点x,f(s,i)=sum{ g(ss,ii)*C(cnt[s-ss],i-ii) | ss为s的真子集且包含x,sz[ss]-1<=ii<=min(i,cnt[ss]),i-ii<=cnt[s-ss] },sz[s]表示集合s中点的数量。(方程的正确性:对于任意一种不连通的情况,一定存在至少两个连通分量,找到一个连通分量并枚举其所有连通的情况,用其方案数乘上对应情况下其他所有点可能的形态方案数累加到答案中)

于是再整理一下:ans=sum{ (g(2N-1,i)/C(M,i) - g(2N-1,i-1)/C(M,i-1)) * i/(M+1) | 1<=i<=M }

实际上到这里就完了但是敏锐的人发现方程中的g换成f之后好像可以化简?!由于原图是连通的所以当选用M条边的时候f(2N-1,M)=0,这样可以把展开后的式子的最后一项剩余的消掉,最后答案写为:ans=sum{ f(2N-1,i)/C(M,i) | 1<=i<M } / (M+1)

是不是很顺理成章?但是真的很抱歉自己想我真的。。。。。。ORZ

精简版本:

g(s,i)表示用i条边将点集s中的点连通的方案数,f(s,i)表示用i条边不能将点集s中的点连通的方案数,有g(s,i)=C(cnt[s],i)-f(s,i),cnt[x]表示两端都在点集x中的边的条数。

令x为s中任意一个点,f(s,i)=sum{ g(ss,ii)*C(cnt[s-ss],i-ii) | ss为s的真子集且包含x,sz[ss]-1<=ii<=min(i,cnt[ss]),i-ii<=cnt[s-ss] },sz[s]表示集合s中点的数量。

ans = sum{ (g(2N-1,i)/C(M,i) - g(2N-1,i-1)/C(M,i-1)) * i/(M+1) | 1<=i<=M } = sum{ f(2N-1,i)/C(M,i) | 1<=i<M } / (M+1)

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int maxn=;
const int maxm=;
const int maxs=(<<)+;
typedef long long LL; int N,M;
int bin[maxn],cnt[maxs],sz[maxs];
LL f[maxs][maxm],g[maxs][maxm],C[maxm][maxm];
struct edge{ int u,v; }E[maxm]; void data_in()
{
scanf("%d%d",&N,&M);
int x,y;
for(int i=;i<=M;i++){
scanf("%d%d",&x,&y);
E[i]=(edge){x,y};
}
}
void dp()
{
for(int i=;i<=N+;i++) bin[i]=<<i-;
for(int i=;i<=M;i++){
C[i][]=;
for(int j=;j<=i;j++)
C[i][j]=C[i-][j]+C[i-][j-];
}
for(int s=;s<bin[N+];s++)
for(int i=;i<=M;i++)
if((bin[E[i].u]&s)&&(bin[E[i].v]&s)) cnt[s]++;
for(int s=;s<bin[N+];s++){
sz[s]=sz[s>>]+(s&);
for(int i=;i<=cnt[s];i++){
if(sz[s]==) g[s][i]=;
else{
int x;
for(x=;x<=N;x++) if(bin[x]&s) break;
for(int ss=(s-)&s;ss;ss=(ss-)&s) if(bin[x]&ss)
for(int ii=sz[ss]-;ii<=min(i,cnt[ss]);ii++)
if(i-ii<=cnt[s^ss])
f[s][i]+=g[ss][ii]*C[cnt[s^ss]][i-ii];
g[s][i]=C[cnt[s]][i]-f[s][i];
}
}
}
}
void work()
{
dp();
double ans=;
int all=bin[N+]-;
for(int i=;i<M;i++)
ans+=1.0*f[all][i]/C[cnt[all]][i];
printf("%.6f\n",ans/(M+));
}
int main()
{
data_in();
work();
return ;
}

BZOJ 3925 ZJOI2015 地震后的幻想乡 状压dp+期望的更多相关文章

  1. BZOJ 3925 ZJOI2015 地震后的幻想乡

    假设我们用了边权前i小的边使得图连通,那么对答案的贡献为i/m+1 又因为期望的线性性质,我们只需要求用了i条边就可以了 不妨设g(S)(i)表示用了i条边使得点集S连通的概率 设f(S)(i)表示用 ...

  2. BZOJ 3925: [Zjoi2015]地震后的幻想乡(概率)

    CLJ就是喜欢出ctsc上讲的东西,看来还是得找时间把他的那几道题做下 首先记f(x)为答案>x的概率,那么把这个东西从0到1积分就是答案了 f(x)<=>边小于x不能使图联通的概率 ...

  3. BZOJ 3925 [Zjoi2015]地震后的幻想乡 ——期望DP

    我们只需要考虑$\sum F(x)P(x)$的和, $F(x)$表示第x大边的期望,$P(x)$表示最大为x的概率. 经过一番化简得到$ans=\frac{\sum T(x-1)}{m+1}$ 所以就 ...

  4. BZOJ 3925: [Zjoi2015] 地震后的幻想乡(概率DP)

    这里有一篇很好很强的博客%%% YouSiki大佬的博客 多理解一会就行了- 代码 #include <bits/stdc++.h> using namespace std; typede ...

  5. 【BZOJ3925】[ZJOI2015]地震后的幻想乡(动态规划)

    [BZOJ3925][ZJOI2015]地震后的幻想乡(动态规划) 题面 BZOJ 洛谷 题解 题目里面有一句提示:对于\(n\)个\([0,1]\)之间的随机变量\(x1,x2,...,xn\),第 ...

  6. 【洛谷3343_BZOJ3925】[ZJOI2015]地震后的幻想乡(状压 DP_期望)

    题目: 洛谷 3343 BZOJ 3925 分析: 谁给我说这是个期望概率神题的,明明没太大关系好吧 「提示」里那个结论哪天想起来再问 Jumpmelon 怎么证. 首先,由于开始修路前 \(e_i\ ...

  7. [bzoj3925] [洛谷P3343] [ZJOI2015] 地震后的幻想乡

    Description 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任 ...

  8. [ZJOI2015]地震后的幻想乡(期望+dp)

    题目描述 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任务是尽快让幻想 ...

  9. BZOJ3925: [Zjoi2015]地震后的幻想乡

    Description 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任 ...

随机推荐

  1. python 实现远程上传文件夹

    python2 upload.py "ip" "root" "password" "22" "Only Pro ...

  2. 菜鸟笔记 -- Chapter 6 面向对象

    在Java语言中经常被提到的两个词汇是类与对象,实质上可以将类看作是对象的载体,它定义了对象所具有的功能.学习Java语言必须要掌握类与对象,这样可以从深层次去理解Java这种面向对象语言的开发理念, ...

  3. ios应用数据存储方式(归档) - 转

    一.简单说明  1.在使用plist进行数据存储和读取,只适用于系统自带的一些常用类型才能用,且必须先获取路径相对麻烦.  2.偏好设置(将所有的东西都保存在同一个文件夹下面,且主要用于存储应用的设置 ...

  4. nodejs+express开发blog(2)

    npm install -g nodemon 1,把ejs文件修改为html文件 app.engine('.html', require('ejs').__express);app.set('view ...

  5. 【TOJ 1912】487-3279(hash+map)

    描述 Businesses like to have memorable telephone numbers. One way to make a telephone number memorable ...

  6. MySQL备份恢复之mydumper

      Preface       In my previous two blogs,we have known about the tool of backing up MySQL db.I'm gon ...

  7. LintCode 12.带最小值操作的栈(两种方法实现)

    题目描述 实现一个带有取最小值min方法的栈,min方法将返回当前栈中的最小值. 你实现的栈将支持push,pop 和 min 操作,所有操作要求都在O(1)时间内完成. 样例 如下操作:push(1 ...

  8. python list统计

    from random import randint data = [randint(0, 20) for _ in xrange(30)] print data # [20, 4, 4, 20, 1 ...

  9. 使用Win32DiskImager后重置SD卡

    再1.Windows diskpart命令 diskpart 2.列出所有的磁盘 lisk disk 3.选择U盘所在的磁盘 4.清除磁盘 clean 5.创建主分区 create primary p ...

  10. ruby Time类与Date类

    Time类用于表示时间.时间除了表示年月日时分秒的信息外,还包含了表示地域时差的时区(time zone)信息.例如我们可以计算中国当前时间是国际协调时间的几点 Date类只用于表示年月日.因此,相对 ...