洛谷 P3343 - [ZJOI2015]地震后的幻想乡(朴素状压 DP/状压 DP+微积分)
鸽子 tzc 竟然来补题解了,奇迹奇迹(
神仙题 %%%%%%%%%%%%
解法 1:
首先一件很明显的事情是这个最小值可以通过类似 Kruskal 求最小生成树的方法求得。我们将所有边按边权从小到大排序并依次加入图中,如果加入边权为 \(v\) 的边后图首次连通,那么这张图对答案的贡献就是 \(v\)。
那么怎么求这个期望值呢?我们考虑枚举加入多少条边后图首次连通,记这个数为 \(c\),那么这种情况对期望的贡献就是 \(\dfrac{c}{m+1}\),如果我们能再求出 \(p_c\) 表示加入 \(c\) 条边后图首次连通的概率,那么即可通过 \(ans=\sum\limits_{i=1}^mp_i\dfrac{i}{m+1}\) 求出答案。
因此现在问题就转化为如何求 \(p_i\),注意到此题 \(n\) 很小,因此考虑状压 \(dp\),我们设 \(f_{S,i}\) 表示在点 \(S\) 中的点之间连 \(i\) 条边后 \(S\) 中的点不连通的方案数,再设 \(g_{S,i}\) 表示在 \(S\) 中的点之间连 \(i\) 条边后 \(S\) 的点不连通的方案数。转移还是相对来说比较容易,我们先预处理出 \(D_S\) 表示 \(S\) 中的点之间总共连出了多少条边。对于 \(f\) 的转移,我们记 \(x\) 为 \(S\) 中最小的元素,即代码实现中的 s&-s
,我们枚举哪些点与 \(x\) 在同一个连通块中,记作 \(T\),再枚举 \(T\) 中的点连了多少条边,那么有 \(f_{S,i}=\sum\limits_{x\in T\subsetneq S}\sum\limits_{j=0}^ig_{T,i}\dbinom{D_{S-T}}{i-j}\)。至于 \(g\) 的转移,显然满足 \(f_{S,i}+g_{S,i}=\dbinom{d_S}{i}\),因为在 \(S\) 中的边选 \(i\) 条边总共只有 \(\dbinom{d_S}{i}\) 种选择。子集枚举转移一下即可,复杂度 \(3^nm^2\)
接下来考虑知道 \(f,g\) 后怎样求出 \(p\),记 \(U=\{1,2,3,\cdots,n\}\),那么 \(p_i\) 显然等于加入 \(i-1\) 条边后不连通的概率减去加入 \(i\) 条边后不连通的概率。而显然加入 \(i\) 条边后不连通的概率显然为 \(\dfrac{f_{U,i}}{\dbinom{m}{i}}\),因此 \(p_i=\dfrac{f_{U,i-1}}{\dbinom{m}{i-1}}-\dfrac{f_{U,i}}{\dbinom{m}{i}}\),代入上面的式子求一下即可。
const int MAXN=10;
const int MAXP=1<<10;
const int MAXM=45;
int n,m,ed[MAXN+5][MAXN+5],d[MAXP+5];
double c[MAXM+5][MAXM+5],f[MAXP+5][MAXM+5],g[MAXP+5][MAXM+5];
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),ed[u][v]++;
for(int i=0;i<(1<<n);i++) for(int j=1;j<=n;j++) for(int k=1;k<=n;k++)
if((i>>j-1&1)&&(i>>k-1&1)) d[i]+=ed[j][k];
for(int i=0;i<=MAXM;i++){
c[i][0]=1;
for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1];
}
for(int i=0;i<(1<<n);i++){
for(int j=0;j<=d[i];j++){
for(int k=i;k;k=(k-1)&i){
if(k&(i&-i)){
for(int l=0;l<=min(d[k],j);l++){
f[i][j]+=g[k][l]*c[d[i^k]][j-l];
}
}
} g[i][j]=c[d[i]][j]-f[i][j];
}
} double ans=0;
for(int i=0;i<=m;i++) ans+=1.0/(m+1)*f[(1<<n)-1][i]/c[m][i];
printf("%.6lf\n",ans);
return 0;
}
解法 2:
此题也可以从积分的角度来理解。
u1s1 这个做法就比上面那个做法不知道神仙多少倍了。
注意到此题涉及连续型变量,因此可以采用微积分,我们记 \(p(t)\) 为将所有边边权从小到大排序后,加入边权为 \(t\) 的边后图首次连通的概率,那么有
ans&=\int_0^1p(x)x\,\mathrm dx\\
&=\int_0^1p(x)\int_0^x\,\mathrm dz\,\mathrm dx\\
&=\int_0^1\int_z^1p(x)\,\mathrm dx\,\mathrm dz
\end{aligned}
\]
如果我们记 \(q(x)\) 为 \(\int_x^1p(z)\,\mathrm dz\),即 \(x\) 时刻图不连通的概率,那么
\]
接下来考虑怎样求这个东西,我们再定义二元函数 \(f(S,t)\) 表示在 \(t\) 时刻 \(S\) 中的点不连通的概率,转移就套路记 \(x\) 为 \(S\) 中最小的元素,并套路地枚举 \(t\) 时刻与 \(x\) 在同一连通块中的点 \(T\),那么显然 \(S-T,T\) 之间所有边的边权都要 \(>t\),我们记这样边的个数为 \(c(S-T,T)\),那么:
\]
但是显然这个 \(f(S,t)\) 不能直接通过类似 DP 的方式求出来,因为它涉及连续变量 \(t\),注意到答案是一个积分形式,因此考虑将 DP 状态也设成一个积分的形式,我们从答案出发,答案要求
\]
即
\]
其中 \(U=\{1,2,3,\cdots,n\}\)。
因此考虑设 \(dp_S=\int_0^1f(S,t)\,\mathrm dt\)。
不过这样一来就有一个问题,在 \(f(S,t)\) 的转移式子中转移出来的不再是 \(\int_0^1f(T,t)\,\mathrm dt\),而是 \(\int_0^1f(T,t)(1-t)^{k}\,\mathrm dt\) 的形式。因此考虑将原来一维 DP 状态扩展到二维,即设 \(dp_{S,k}=\int_0^1f(S,t)(1-t)^k\,\mathrm dt\),那么有如下转移:
dp_{S,k}&=\int_0^1f(S,t)(1-t)^k\,\mathrm dt\\
&=\int_0^1\sum\limits_{x\in T\subsetneq S}(1-f(T,t))(1-t)^{c(S-T,T)}·(1-t)^k\,\mathrm dt\\
&=\int_0^1\sum\limits_{x\in T\subsetneq S}((1-t)^{c(S-T,T)+k}-f(T,t)(1-t)^{c(S-T,T)+k})\,\mathrm dt\\
&=\sum\limits_{x\in T\subsetneq S}\int_0^1(1-t)^{c(S-T,T)+k}\,\mathrm dt-\int_0^1f(T,t)(1-t)^{c(S-T,T)+k}\,\mathrm dt\\
\end{aligned}
\]
注意到左边的东西可以转化为
\]
这显然就是一个幂函数的积分,记 \(F(x)=\int_0^xt^{c(S-T,T)+k}\,\mathrm dt\),那么 \(F(x)=\dfrac{x^{c(S-T,T)+k+1}}{c(S-T,T)+k+1}\)
将 \(x=1\) 代入得原式 \(=\dfrac{1}{c(S-T,T)+k+1}\)
再看右边,这显然可以通过前面的 DP 状态推出来,这玩意儿显然就等于 \(dp_{T,c(S-T,T)+k}\)
故 \(dp_{S,k}=\dfrac{1}{c(S-T,T)+k+1}-dp_{T,c(S-T,T)+k}\),简单递推求一下,最终答案即为 \(dp_{U,0}\)
时间复杂度 \(3^nm\),比上面的解法少一个 \(m\)。
const int MAXN=10;
const int MAXM=45;
const int MAXP=1<<10;
int n,m,con[MAXN+5];
double f[MAXP+5][MAXM+5];
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
con[u]|=(1<<v-1);con[v]|=(1<<u-1);
}
for(int i=1;i<(1<<n);i++) if(i&1){
for(int j=i;j;j=(j-1)&i) if((j^i)&&(j&1)){
int cnt=0;
for(int k=1;k<=n;k++) if((i>>(k-1)&1)&&(~j>>(k-1)&1)) cnt+=__builtin_popcount(con[k]&j);
for(int k=0;k+cnt<=m;k++) f[i][k]+=1.0/(1+k+cnt)-f[j][k+cnt];
}
} printf("%.6lf\n",f[(1<<n)-1][0]);
return 0;
}
洛谷 P3343 - [ZJOI2015]地震后的幻想乡(朴素状压 DP/状压 DP+微积分)的更多相关文章
- [bzoj3925] [洛谷P3343] [ZJOI2015] 地震后的幻想乡
Description 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任 ...
- 洛谷P3343 [ZJOI2015]地震后的幻想乡 [DP,概率期望]
传送门 思路 题目给了一个提示:对于\(n\)个\([0,1]\)的随机变量,其中第\(k\)小的期望大小是\(\frac{k}{n+1}\). 这引导我们枚举边的相对大小的全排列,然后求最小生成树 ...
- 洛谷3343(ZJOI2015)地震后的幻想乡
题目:https://www.luogu.org/problemnew/show/P3343 1.那个时间与边的大小排名有关,所以需要求一下最大边的期望排名就行. 2.期望排名是这样算的:(排名为1的 ...
- P3343 [ZJOI2015]地震后的幻想乡
传送门 给积分大佬跪了 再给状压大佬也跪了 //minamoto #include<bits/stdc++.h> #define rint register int #define ll ...
- 【BZOJ3925】[ZJOI2015]地震后的幻想乡(动态规划)
[BZOJ3925][ZJOI2015]地震后的幻想乡(动态规划) 题面 BZOJ 洛谷 题解 题目里面有一句提示:对于\(n\)个\([0,1]\)之间的随机变量\(x1,x2,...,xn\),第 ...
- 【洛谷3343_BZOJ3925】[ZJOI2015]地震后的幻想乡(状压 DP_期望)
题目: 洛谷 3343 BZOJ 3925 分析: 谁给我说这是个期望概率神题的,明明没太大关系好吧 「提示」里那个结论哪天想起来再问 Jumpmelon 怎么证. 首先,由于开始修路前 \(e_i\ ...
- 题解-ZJOI2015地震后的幻想乡
Problem bzoj & 洛谷 题意简述:给定一个\(n\)(\(n\leq 10\))个点\(m\)条边的无向图,每条边的权值为一个\(0\)到\(1\)之间的连续随机变量,求图的最小生 ...
- BZOJ3925: [Zjoi2015]地震后的幻想乡
Description 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任 ...
- [ZJOI2015]地震后的幻想乡(期望+dp)
题目描述 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任务是尽快让幻想 ...
随机推荐
- 整理一下在 npmjs.com 上面发布资源包踩过的坑
正常流程就不说了,网上有很多,比如写代码.打包.注册.登录.发布等. 邮箱要激活 在 npmjs.com 上面注册账号的时候需要填写邮箱,然后登录网址的时候并没有强制要求你去邮箱激活. 但是到了发布资 ...
- js判断移动端浏览器类型,微信浏览器、支付宝小程序、微信小程序等
起因 现在市场上各种跨平台开发方案百家争鸣各有千秋,个人认为最成熟的还是hybird方案,简单的说就是写H5各种嵌入,当然作为前端工程师最希望的也就是公司采用hybird方案当作技术路线. 所谓的hy ...
- Gopher们写if err != nil是否腻了?
效果 go里面没有try catch,比较类似的有panic() 和 recover()机制,但是代价太大了,他们的场景更多使用在"程序异常,无法继续往下执行了这种场景",比如配置 ...
- oo第三次博客-JML规格
这三周的作业主要是围绕以JML来约束代码开发,以确保程序的正确性与鲁棒性. Part 1:三次作业的实现与bug 第一次作业没有任何算法和数据结构上的难度,对于Path和PathContainer的各 ...
- 微服务(三) Eureka注册中心和Ribbon负载均衡
1. Eureka注册中心 1.1 Eureka的结构和作用 在上一篇文章中 微服务(二)服务拆分及远程调用 order-service在发起远程调用的时候,该如何得知user-service实例的i ...
- 记录编译QGIS(3.4+Qt5.11+VS2015)的整个过程
编译运行整个QGIS耗时耗力,由于本人比较愚钝,来来回回花了大概两个星期最终编译成功,记录一下整个过程,一方面备忘,另一方面可能也给别人一点借鉴. 1.准备工作 参考了许多网上的教程,李民录大神的&l ...
- Linux基础是零基础必须要过的关,你懂了多少
#LINUX基础学习 ##命令行下的基础知识 Linux区分英文的大小写. date :查看时间 cal:查看日历 [Tab] 热键 :可以自动补全命令名和文件名 [Ctrl]+C 热键 :可以中断正 ...
- 【做题记录】DP 杂题
P2577 [ZJOI2004]午餐 $\texttt{solution}$ 想到贪心: 吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 状态: \(f[i][j]\) 表示前 \(i\ ...
- [转]DDR3基础知识介绍
本文转自:(4条消息) xilinx ddr3 MIG ip核使用详解_admiraion123的博客-CSDN博客 1,DDR3基本内容介绍1.1,DDR3简介DDR3全称double-data-r ...
- linux updatedb: can not open a temporary file for `/var/lib/mlocate/mlocate.db'
我们想查找我们最新创建的文件时,由于locate的数据库是每天更新.所以我们新创建的文件还没有被更新到系统的数据库. 这是需要手动更新数据库. 然后就可以查到. updatedb 输出 updated ...