POJ 3156 - Interconnect (概率DP+hash)
题意:给一个图,有些点之间已经连边,现在给每对点之间加边的概率是相同的,问使得整个图连通,加边条数的期望是多少。
此题可以用概率DP+并查集+hash来做。
用dp(i,j,k...)表示当前的每个联通分量的点数分别是i,j,k...(连通分量的个数不固定)时,加边的期望。
这样以dp(i,j,k)为例分析状态转移的过程,dp(i,j,k)=p1*dp(i,j,k)+p2*dp(i+j,k)+p3*dp(i,j+k)+p4*dp(j,i+k)+1。
终止条件是dp(n)=0,因为此时图一定联通,所以期望是0。
这个式子是怎么来的呢?
p1*dp(i,j,k)表示增加了一条边之后原来的联通分量没有改变时的情况,p1表示选中这样的无用边的概率;p2*dp(i+j,k)表示增加了一条连结i和j这两个联通分量的边,p2表示选中i和j之间的边的概率。最后的1表示增加了一条边。
这里我们要计算选边概率。
首先有n*(n-1)/2条边。
如果选中了不改变图的联通分量的边,此时说明每次加的边都属于一个连通分量,所以一共有sum{(cnt(i)*cnt(i)-1)/2}(cnt(i)表示该联通分量内有cnt(i)个点)种选择情况。
如果选中了某条边连结了某两个联通分量i、j,这个时候一共有cnt(i)*cnt(j)种情况。
计算概率只需要除以边的总数即可。
计算连通分量可以用并查集。
因为这个题只看图的连通情况不在乎具体是哪个点,因此可以对每个联通分量的点数排序,使得每个状态唯一,这样可以得到很多重叠的子问题,整个问题就可以用记忆化搜索完成了。
很明显问题的状态比较复杂,直接下手很难处理也容易超时,所以用hash处理状态压缩判重。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #define MOD 100007 using namespace std; int n,m; struct State { double val; ]; bool vis; State() { memset(x,,sizeof(x)); vis=false; } void clear() { memset(x,,sizeof(x)); vis=false; } void mysort() { sort(x,x+); } int myhash() const { ; ,b=; i>=&&x[i]; --i) { res+=x[i]*b; res%=MOD; b*=; b%=MOD; } return res; } bool operator ==(State &t)const { ; i<; ++i) if(x[i]!=t.x[i]) return false; return true; } bool operator !=(State &t) const { return !(*this==t); } }; State has[MOD+],st; void inserthash(State &p) { int v=p.myhash(); while(has[v].vis) ; has[v]=p; has[v].vis=true; } double gethash(State &p) { int v=p.myhash(); while(has[v].vis&&has[v]!=p) ; ; } ]; int find(int p) { return p==father[p]?p:(father[p]=find(father[p])); } void init() { ; i<=n; ++i) father[i]=i; st.clear(); } double DP(State &s) { ; double v=gethash(s); if(v!=-1.0) return v; ,sn=n*(n-)/2.0;; ; i>=&&s.x[i]; --i) q+=s.x[i]*(s.x[i]-)/2.0; double &res=s.val; res=; ; i>=&&s.x[i]; --i) ; j>=&&s.x[j]; --j) { double p=s.x[i]*s.x[j]/sn; State t; ; k>=; --k) if(k!=i&&k!=j) t.x[k]=s.x[k]; else if(k==i) t.x[k]=s.x[i]+s.x[j]; ; t.mysort(); res+=p*DP(t); } res=res/(-q/sn); inserthash(s); return res; } ]; int main() { while(scanf("%d%d",&n,&m)!=EOF) { init(); ; i<m; ++i) { int x,y; scanf("%d%d",&x,&y); int fx=find(x),fy=find(y); if(fx!=fy) father[fx]=fy; } memset(cnt,,sizeof(cnt)); ; i<=n; ++i) cnt[find(i)]++; ; i<=n; ++i) st.x[i-]=cnt[i]; st.mysort(); printf("%.6f\n",DP(st)); } ; }
学习了http://www.cnblogs.com/swm8023/archive/2012/09/21/2696593.html。
POJ 3156 - Interconnect (概率DP+hash)的更多相关文章
- poj 1322 Chocolate (概率dp)
///有c种不同颜色的巧克力.一个个的取.当发现有同样的颜色的就吃掉.去了n个后.到最后还剩m个的概率 ///dp[i][j]表示取了i个还剩j个的概率 ///当m+n为奇时,概率为0 # inclu ...
- POJ 3071 Football(概率DP)
题目链接 不1Y都对不住看过那么多年的球.dp[i][j]表示i队进入第j轮的概率,此题用0-1<<n表示非常方便. #include <cstdio> #include &l ...
- Scout YYF I POJ - 3744(概率dp)
Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into th ...
- POJ - 2151 (概率dp)
题意:有T个队伍,有M道题,要求每个队至少有一道题,并且有队伍至少过N道题的概率. 这个题解主要讲一下,后面的,至少有一道题解决和至少一道题至N-1道题解决,到底怎么算的,其实,很简单,就是母函数. ...
- poj 3071 Football (概率DP水题)
G - Football Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit ...
- POJ 1202 Family 概率,DP,高精 难度:2
http://poj.org/problem?id=1202 难度集中在输出格式上,因为输出格式所以是高精度 递推式: 血缘肯定只有从双亲传到儿子的,所以,设f,m为双亲,son为儿子,p[i][j] ...
- poj 3071 Football(概率dp)
id=3071">http://poj.org/problem? id=3071 大致题意:有2^n个足球队分成n组打比赛.给出一个矩阵a[][],a[i][j]表示i队赢得j队的概率 ...
- 【POJ】2151:Check the difficulty of problems【概率DP】
Check the difficulty of problems Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8903 ...
- POJ 2096 Collecting Bugs (概率DP,求期望)
Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material stu ...
随机推荐
- AC自动机 & Fail树 专题练习
Fail树就是AC自动机建出来的Fail指针构成的树. [bzoj3172][xsy1713]单词 题意 给定一些单词,求每个单词在所有单词里面的出现次数. 分析 构建Fail树,记录每个单词最后一个 ...
- github如何pull最新代码
github现在已经经常用了,但是经常遇到下面的问题 比如:从一个项目A中fork了一个分支B,并且在分支B有了改动.过了几天后,项目A中的代码应该会有很多人提交修改了,现在想将最新的代码pull ...
- $('#checkbox').attr('checked'); 返回的是checked或者是undefined解决办法
$('#checkbox').attr('checked'); 返回的是checked或者是undefined解决办法 <input type='checkbox' id='cb'/> ...
- Login 页面
1.jsp <script type="text/javascript"> function doLogin() { if (trim($('#username').v ...
- 集成 AliPay - 支付宝
作者感言 前面我已经写了一篇关于WeChat SDK的支付篇, 那我们继续研究接下来的支付SDK, 这次就是国民支付软件支付宝, 下面就让我们来看看怎么集成AliPay SDK.最后:如果你有更好的建 ...
- hadoop主节点(NameNode)备份策略以及恢复方法
link:http://jiajun.iteye.com/blog/809125 一.dits和fsimage 首先要提到两个文件edits和fsimage,下面来说说他们是做什么的. 集群中的名称节 ...
- wordpress+php+mysql 配置
下载并解压wordpress之后,在mysql新建一个数据库,命名,例如testDB1,然后在IIS中新建虚拟目录,指向wordress所在的目录,删除wordpress目录下的wp-config.p ...
- 企业级的响应式设计(Responsive design at enterprise level)译
导言 响应式设计是现在人们谈论的热点,但如何部署,特别是在有多种设备的大型项目中如何组织响应式设计,响应式设计和可伸缩性(Scalable)有什么区别?这都是需要解决的难题. 优化用户经验——Opti ...
- MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式
文章索引和简介 通过上一篇的学习 我们把demo的各种关系终于搭建里起来 以及处理好了如何映射到数据库等问题 但是 只是搭建好了关系 问题还远没有解决 这篇就来写如何查找导航属性 和查找导航属性的几种 ...
- 对于transform的新认识
transform-origin是作用于该元素自己的,transform-origin(0px,0px),是以该元素自己本身的左上角(0px,0px)为圆心进行动作的.