标签:
http://acm.hdu.edu.cn/showproblem.php?pid=4035
有N(2 ≤ N ≤ 10000)个房间和一堆双向边(不存在环),每个房间有ki和ei两个值,分别代表回到房间1和游戏结束的概率,求游戏结束时通过的边数的期望
一道很好很经典的求期望的题
设E[i]为以i为起点,直到游戏结束所通过边数的期望,则E[1]即所求答案
设fa代表父亲节点(由于不存在环,则图为一棵树,设1为根节点),∑ch代表所有孩子节点,size代表与这个房间直接相连的房间数,设X=1-ki-ei
可以推导出 E[i]=ki*E[1]+X*(1/size*(E[fa]+1/size*∑E[ch])+1)---公式1
设 E[i]=a[i]*E[1]+b[i]*E[fa]+c[i]
则 ∑E[ch]=∑(a[ch]*E[1]+b[ch]*E[i]+c[ch])
代入公式1可得 E[i]=( (ki+X/size*∑a[ch])*E[1]+X/size*∑E[fa]+X+X/size*∑(c[ch]) ) /(1-X/size*b[ch])
对比可得
a[i]=(ki+X/size*∑a[ch])/(1-X/size*b[ch])
b[i]=X/size/(1-X/size*b[ch])
c[i]=(X+X/size*c[ch])/(1-X/size*b[ch])
E[1]=a[1]*E[1]+b[1]*E[fa]+c[1]=(a[1]*E[fa]+c[1])/(1-a[1])=c[1]/(1-a[1])
#include<stdio.h>
#include<vector>
#include<math.h>
using namespace std;
const int N=10005;
const double eps=1e-9;
vector<int>q[N];
bool mark[N];
int fa[N],out[N],que[N],head,tail;
double k[N],e[N],A,B,C;
void dfs(int x=1)
{
bool leaf=true;
double p=1-k[x]-e[x];
mark[x]=true;
int m=q[x].size();
double a=0.0,b=0.0,c=0.0;
for(int i=0;i<q[x].size();++i)
{
fa[q[x][i]]=x;
if(!mark[q[x][i]])
{
leaf=false;
dfs(q[x][i]);
a+=A,b+=B,c+=C;
}
}
if(leaf)
{
A=k[x];
B=C=p;
}
else
{
A=(k[x]+p/m*a)/(1-p/m*b);
B=p/m/(1-p/m*b);
C=(p+p/m*c)/(1-p/m*b);
}
}
int main()
{
int T,n,x,y,leaf,w=0;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
out[i]=0,mark[i]=false,q[i].clear();
for(int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
q[x].push_back(y);
q[y].push_back(x);
}
for(int i=1;i<=n;++i)
{
scanf("%lf%lf",&k[i],&e[i]);
k[i]/=100.0,e[i]/=100.0;
}
dfs();
printf("Case %d: ",++w);
if(fabs(1-A)<eps)printf("impossible\n");
else printf("%.6f\n",C/(1-A));
}
}
标签:
原文地址:http://www.cnblogs.com/kiuhghcsc/p/5571295.html