2019南京网络赛 D Robots 期望dp

给出一个 n ≤ 4 e 5 , m ≤ 5 e 5 n\leq4e5,m\leq5e5 n4e5m5e5的有向图,并且保证起点 1 1 1是唯一的,终点 n n n也是唯一的,每次有等同的概率停留在原地或者走到下一个点,每次走到新的点要耗费一天的代价,走到每个点的得分是走到这个点的天数。求问最终走到终点的得分的期望。
可以拆成两部分来做。 E 1 ( u ) E_{1}(u) E1(u)表示从 u u u到终点的天数期望。u转移有 E 1 ( u ) = E 1 ( u ) d e g [ u ] + 1 + ∑ E 1 ( v ) d e g [ u ] + 1 + 1 E_{1}(u)=\frac{E_{1}(u)}{deg[u]+1}+\frac{\sum E_{1}(v)}{deg[u]+1}+1 E1(u)=deg[u]+1E1(u)+deg[u]+1E1(v)+1,然后再去求 E 2 ( u ) E_{2}(u) E2(u)表示 u u u到终点的的得分期望。 E 2 ( u ) = E 2 ( u ) d e g [ u ] + 1 + ∑ E 2 ( v ) d e g [ u ] + 1 + E 1 ( u ) E_{2}(u)=\frac{E_{2}(u)}{deg[u]+1}+\frac{\sum E_{2}(v)}{deg[u]+1}+E_{1}(u) E2(u)=deg[u]+1E2(u)+deg[u]+1E2(v)+E1(u)
记忆化搜索转移就好了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=1e5+7;
vector<int> G[N]; 
double dp1[N],dp2[N]; 
int deg[N]; 
int n,m; 
double dfs1(int u) {
	if(u==n) return 0;
	if(dp1[u]) return dp1[u]; 
	double ans=0.0;
	for(auto &v:G[u]) {
		ans+=dfs1(v);	
	}
	return dp1[u]=ans/deg[u]+1.0+1.0/deg[u];
}
double dfs2(int u) {
	if(u==n) return 0;
	if(dp2[u]) return dp2[u];
	double ans=0.0;
	for(auto &v:G[u]) {
		ans+=dfs2(v);
	}
	return dp2[u]=ans/deg[u]+dp1[u]+dp1[u]/deg[u];
}
int main() {
	int T;
	scanf("%d",&T);
	while(T--) {
		memset(dp1,0,sizeof(dp1));
		memset(dp2,0,sizeof(dp2)); 
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) {
			G[i].clear(); 
			deg[i]=0;
		}
		for(int i=1;i<=m;i++) {
			int u,v;
			scanf("%d%d",&u,&v);
			G[u].push_back(v);
			deg[u]++;
		}
		dfs1(1);
		double ans=dfs2(1);
		printf("%.2lf\n",ans); 
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值