首页 > 其他分享 >题解 HDU4035 【Maze】

题解 HDU4035 【Maze】

时间:2022-11-14 20:00:59浏览次数:69  
标签:right frac int 题解 sum times HDU4035 Maze left

posted on 2022-08-17 12:33:51 | under 题解 | source

problem

https://vjudge.net/problem/HDU-4035

SHY 在一棵树上随机游走,从根节点出发,每次有 \(k_u\) 的几率回到根节点,\(e_u\) 的几率到达出口,否则随机选择一个与它相连的节点并走过去,求期望多少步能走到出口。\(1\leq n\leq 10^4\)。

solution

令根为 \(1\),\(t_u=1-k_u-e_u\),记 \(f_u\) 表示从点 \(u\) 出发走到出口的期望步数,\(p\) 为 \(u\) 的父亲,\(v\) 为 \(u\) 的儿子,\(d\) 为点 \(u\) 的度数。显然有:

\[\begin{aligned} f_u&=k_u\times f_1+t_u\times\sum_{v\in son(u)}d^{-1}(f_v+1)+t_u\times d^{-1}(f_p+1)\\ &=k_u\times f_1+t_u\times d^{-1}\times\left(f_p+1+\sum_{v\in son(u)}(f_v+1)\right)\\ &=k_u\times f_1+t_u\times d^{-1}\times f_p+t_u\times d^{-1}\times \sum_{v\in son(u)}f_v+t_u\\ \end{aligned}\]

我们发现这个式子有后效性,那么当然不能打高斯消元,考虑令 \(f_u=a_u\times f_1+b_u\times f_p+c_u\)。分类讨论:对于一片叶子,显然有 \(a_u=k_u,b_u=c_u=t_u\)。

对于非叶子节点 \(u\),我们考虑拆掉 \(\sum_{v\in son(u)}f_v=f_1\times\sum a_v+f_u\times\sum b_v+\sum c_v\)。

\[\begin{aligned} f_u&=k_u\times f_1+\frac{t_u}{d}\times f_p+\frac{t_u}{d}\times \sum_{v\in son(u)}f_v+t_u\\ &=k_u\times f_1+\frac{t_u}{d}\times f_p+\frac{t_u}{d}\times \left(f_1\times\sum a_v+f_u\times\sum b_v+\sum c_v\right)+t_u\\ &=\left(k_u+\frac{t_u}{d}\times\sum a_v\right)\times f_1+\frac{t_u}{d}\times f_p+\left(\frac{t_u}{d}\times\sum b_v\right)\times f_u+\left(t_u+\frac{t_u}{d}\times\sum c_v\right) \end{aligned}\]

接下来是点睛之笔:把 \(f_u\) 项移到等式左边!

\[\begin{aligned} f_u&=\left(k_u+\frac{t_u}{d}\times\sum a_v\right)\times f_1+\frac{t_u}{d}\times f_p+\left(\frac{t_u}{d}\times\sum b_v\right)\times f_u+\left(t_u+\frac{t_u}{d}\times\sum c_v\right)\\ f_u-\left(\frac{t_u}{d}\times\sum b_v\right)\times f_u&=\left(k_u+\frac{t_u}{d}\times\sum a_v\right)\times f_1+\frac{t_u}{d}\times f_p+\left(t_u+\frac{t_u}{d}\times\sum c_v\right)\\ \left(1-\frac{t_u}{d}\times\sum b_v\right)\times f_u&=\left(k_u+\frac{t_u}{d}\times\sum a_v\right)\times f_1+\frac{t_u}{d}\times f_p+\left(t_u+\frac{t_u}{d}\times\sum c_v\right)\\ \end{aligned}\]

将 \(1-\frac{t_u}{d}\times\sum b_v\) 作为分母移过去,我们终于得到:

\[\begin{aligned} a_u&=\frac{k_u+\frac{t_u}{d}\times\sum a_v}{1-\frac{t_u}{d}\times\sum b_v}\\ b_u&=\frac{t_u\times d^{-1}}{1-\frac{t_u}{d}\times\sum b_v}\\ c_u&=\frac{t_u+\frac{t_u}{d}\times\sum c_v}{1-\frac{t_u}{d}\times\sum b_v}\\ \end{aligned}\]

这里的每一项都只和 \(u,v\) 有关,可以做树型 DP 了!自底向上更新 \(a_u,b_u,c_u\) 即可。我们其实并不需要计算 \(f_u\)。

最终的答案是 \(f_1=a_1\times f_1+c_1\),可化简为 \(f_1=\frac{c_1}{1-a_1}\)。

什么时候会无解呢?分母是 \(0\) 的时候。

  • \(d=0\) 根本除不动(?????)
  • 计算过程中 \(1-\frac{t_u}{d}\times\sum b_v=0\),寄。
  • 最终 \(a_1=1\),相减又得 \(0\),寄。

那么我们可以写代码了。

code

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
const double eps=1e-9;
template<int N,int M,class T=int> struct graph{
    int head[N+10],nxt[M*2+10],cnt;
    struct edge{
        int u,v;T w;
        edge(int u=0,int v=0,T w=0):u(u),v(v),w(w){}
    } e[M*2+10];
    graph(){memset(head,cnt=0,sizeof head);}
    edge operator[](int i){return e[i];}
    void add(int u,int v,T w=0){e[++cnt]=edge(u,v,w),nxt[cnt]=head[u],head[u]=cnt;}
    void link(int u,int v,T w=0){add(u,v,w),add(v,u,w);}
};
int n,deg[10010];
double a[10010],b[10010],c[10010],k[10010],t[10010];
graph<10010,10010> g;
int dfs(int u,int fa){
	if(deg[u]==1&&fa) return a[u]=k[u],b[u]=c[u]=t[u],1;
    //			^~~~ important!
	double sa=0,sb=0,sc=0;
	for(int i=g.head[u];i;i=g.nxt[i]){
		int v=g[i].v; if(v==fa) continue;
		if(!dfs(v,u)) return 0;
		sa+=a[v],sb+=b[v],sc+=c[v];
	}
	double del=t[u]/deg[u],tmp=1-del*sb;
	if(fabs(tmp)<eps) return 0;
	a[u]=(k[u]+del*sa)/tmp;
	b[u]=del/tmp;
	c[u]=(t[u]+del*sc)/tmp;
	return 1;
}
int mian(){
	for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),g.link(u,v),deg[u]++,deg[v]++;
	for(int u=1;u<=n;u++) scanf("%lf%lf",&k[u],&t[u]),k[u]/=1e2,t[u]/=1e2,t[u]=1-t[u]-k[u];
	if(dfs(1,0)&&fabs(1-a[1])>eps) printf("%.6lf\n",c[1]/(1-a[1]));
	else puts("impossible"); 
	return 0;
}
void reset(){
	static int ccf=0;
	printf("Case %d: ",++ccf);
	memset(a,0,sizeof a);
	memset(b,0,sizeof b);
	memset(c,0,sizeof c);
	memset(k,0,sizeof k);
	memset(t,0,sizeof t);
	memset(deg,0,sizeof deg);
	memset(g.head,g.cnt=0,sizeof g.head); 
}
int main(){
//	#ifdef LOCAL
//	 	freopen("input.in","r",stdin);
//	#endif
	for(scanf("%*d");~scanf("%d",&n);reset(),mian());
	return 0;
}

标签:right,frac,int,题解,sum,times,HDU4035,Maze,left
From: https://www.cnblogs.com/caijianhong/p/solution-HDU4035.html

相关文章

  • ARC 103 /\/\/\/ 题解
    前缀和一下,就好了#include<bits/stdc++.h>usingnamespacestd;typedefunsignedlonglongull;constintN=1e5+99;inta[N],odd[N],even[N];structcmp{ boolo......
  • CSP-S 2022 题解
    T1假期计划\(\ttloj3899\)/\(\ttuoj773\)首先数据规模是\(n\le2500\),提示我们用\(\mathcalO\left(n^2\right)\)的算法。既然是选择\(4\)个互不相同的点,不妨......
  • 题解:【ABC245F】Endless Walk
    题目链接本题解适合像我这样的不具备思维能力的选手。首先根据题意,一个点如果符合要求,那它必然在一个点数大于\(2\)的强联通分量里,因为如果只有一个点它就哪里都去不了......
  • Codeforces 722 F Cyclic Cipher 题解 (同余方程,two-pointers)
    题目链接前两天做过一个题意类似但做法不类似的题在这里首先做这道题需要一个结论:(一元)同余方程组有解的充要条件是方程组中的所有方程两两联立有解。证明两个同......
  • CF1650G 『Counting Shortcuts』 题解
    从洛谷博客那里搬过来的(图论专题本来打算先挑最简单的做,结果做了两个多小时(题意就是让你找从起点\(s\)到终点\(t\)的最短路以及次短路个数,本题次短路长度指的是最短......
  • Codeforces 833 题解
    A\(n\)是奇数时恰好可以用完,\(n\)是偶数时多出来的一块没用,所以直接输出\((n+1)/2\)即可。B每个字符出现次数都小于等于字符总数,令\(\Sigma\)是字符集大小,那显然......
  • CF1292E Rin and The Unknown Flower 题解
    IO交互题fflush(stdout)害人不浅!!1注意到如果我们发起询问C和O就可以花费2的代价知道整个串,不过代价过高,所以我们考虑减小点代价。考虑发起询问CO,CH,CC,这样我......
  • TheNameCalculator题解
    TheNameCalculator题解题目链接:TheNameCalculator题解首先看程序开启的保护,有Canary和NX栈不可执行。IDA打开程序,shift+F12查看字符串,发现有"Hereisyourflag:"。点......
  • 833——B题题解
    题目链接题目大意:给一串字符串(只包含0~9),定义一个最优子串的定义:如果该子串同字符种类数大于最最多字符出现数,那么这个子串可以被称为最优子串。解题思路:大眼一看这个数......
  • [ARC086F] Shift and Decrement 题解
    linkSolution一个简易的贪心想法是我们肯定是对于一个相同的序列求出操作到它的最小操作次数,看能否\(\leK\)。注意到我们在第\(x\)次A操作后进行\(-1\)操作相当于......