绿豆蛙的归宿(luogu)(期望DP)

题目地址
配套地址

在这里插入图片描述

逆向:
设E(i) 表示到i点到n点需要的期望步数
仅考虑 x -> y这一条边,边权为w。
设 y 点所连的各个点的边权为 l 1 , l 2 , . . . , l n l_1,l_2,... ,l_n l1l2...ln,概率为 p 1 , p 2 , . . . , p n p_1,p_2,...,p_n p1p2...pn
那么 E(y) = p 1 l 1 + p 2 l 2 + . . . + p n l n p_1l_1 + p_2l_2 + ... + p_nl_n p1l1+p2l2+...+pnln
E(x) = p 1 ( l 1 + w ) + p 2 ( l 2 + w ) + . . . + p n ( l n + w ) p_1(l_1+w) + p_2(l_2+w) + ... + p_n(l_n+w) p1(l1+w)+p2(l2+w)+...+pn(ln+w)
即等于 E(y) + w ∗ ∑ i = 1 n p i w*\sum_{i=1}^{n}p_i wi=1npi
注意理解 p i p_i pi的含义,表示为y点到它后面连接点的概率。
∑ i = 1 n p i = 1 \sum_{i=1}^{n}p_i = 1 i=1npi=1
即 E(x) = E(y) + w
注意是当仅考虑 x -> y一条边时,那么考虑多边。
E(x) = (E(y) + w) * p i p_i pi,此时的概率就为x的出度的数量。

正向:
设E(i) 表示到1~i点需要的期望步数
仅考虑 x -> y这一条边,边权为w。
设 x 点所连的各个点的边权为 l 1 , l 2 , . . . , l n l_1,l_2,... ,l_n l1l2...ln,概率为 p 1 , p 2 , . . . , p n p_1,p_2,...,p_n p1p2...pn
那么 E(x) = p 1 l 1 + p 2 l 2 + . . . + p n l n p_1l_1 + p_2l_2 + ... + p_nl_n p1l1+p2l2+...+pnln
E(y) = p 1 ( l 1 + w ) + p 2 ( l 2 + w ) + . . . + p n ( l n + w ) p_1(l_1+w) + p_2(l_2+w) + ... + p_n(l_n+w) p1(l1+w)+p2(l2+w)+...+pn(ln+w)
即等于 E(x) + w ∗ ∑ i = 1 n p i w*\sum_{i=1}^{n}p_i wi=1npi
注意理解 p i p_i pi的含义,表示为i点到它后面的x点的概率。
∑ i = 1 n p i ≠ 1 \sum_{i=1}^{n}p_i \neq 1 i=1npi=1
举个例子: a -> x ,a -> b 那么a到x的概率为 1 2 \frac{1}{2} 21
所以上述维护上述两个变量E和p就行。

逆向代码:

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;

int e[N],ne[N],h[N],w[N],idx=1;
int si[N],n,m,d[N];
double dp[N];

void add(int a,int b,int c){
	w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void top_sort(){
	queue<int> qe;
	qe.push(n);
	while(!qe.empty()){
		int t = qe.front();qe.pop();
		for(int i=h[t];i;i=ne[i]){
			int j = e[i];
			dp[j] += (w[i] + 1.0 * dp[t]) / si[j];
			if(--d[j] == 0) qe.push(j);
		}
	}
	cout<<fixed<<setprecision(2)<<dp[1]<<endl;
}

signed main(){
	IOS
    cin>>n>>m;
	for(int i=1;i<=m;i++){
		int a,b,c; cin>>a>>b>>c;
		add(b,a,c);
		d[a] ++;
		si[a] ++;
	}
    top_sort();
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值