[题解]HDU4035 Maze

题目描述

一棵\(n\)个节点的树,从1号结点开始游戏,在每一个点\(x\)

  • \(a[x]/100\)的可能掉进陷阱死翘翘回到1重新开始
  • \(b[x]/100\)的可能找到出口并结束游戏
  • 剩下的可能中,你等概率随机选一条和它相连的边(可以是父亲)走过去

问期望多少步结束游戏

\(1\leq T \leq 30,1\leq n \leq 10000\)

分析

\(dp[x]\)表示位于\(x\)节点时,期望走几步才能结束游戏

那么\(dp[x]=0.01a[x]*dp[1]+0.01b[x]*0+0.01(1-a[x]-b[x])*(\frac{1}{cnt}(\sum dp[son]+dp[1]+1))\)

看了一下数据范围发现并不能承受高斯消元的时间复杂度

我们发现,每一个点的\(dp\)值之和父亲、1号点还有儿子有关,那么叶子节点的\(dp\)值可以用父亲和1号点表示,这样往上代,合并同类项之后可以发现,每一个点的值都可以表示为:

\(dp[x]=...*dp[1]+...*dp[fa[x]]+...\)(常数项)

所以只需要维护一下每一项的系数就可以\(O(n)\)求解了,记得特判Impossible

代码

void SEARCH(int x,int pa){
	f[x][0]=f[x][1]=f[x][2]=0;
	int cnt=0;
	for(int r=lst[x];r;r=nxt[r]){
		cnt++;
 		if(edge[r]==pa)continue;
		SEARCH(edge[r],x);
	}
	DB lef=(100-a[x]-b[x])*0.01;
	DB hlp=0;
	for(int r=lst[x];r;r=nxt[r]){
		if(edge[r]==pa)continue;
		int pos=edge[r];
		f[x][0]+=f[pos][0];
		f[x][2]+=f[pos][2];
		hlp+=f[pos][1];
	}
	f[x][0]=(lef*f[x][0])/(1.0*cnt)+a[x]*0.01;
	f[x][2]=(lef*f[x][2])/(1.0*cnt)+lef;
	if(x==1)f[x][1]=0;else f[x][1]=lef/(1.0*cnt);
	hlp=hlp*lef/(1.0*cnt);
	hlp=1.0-hlp;
	if(x==1)hlp-=f[x][0];
	if(hlp<=0)f[x][0]=f[x][1]=f[x][2]=0;
	else rep(i,0,2)f[x][i]/=hlp;
}
posted @ 2019-11-10 18:25  硫氯  阅读(115)  评论(0编辑  收藏  举报