两种方法,正推和逆推
逆推:\(dp[i]\)表示从\(i\)到\(n\)的期望,方程的转移:对于一条从\(x\)到\(y\)边
\(dp[x]=\sum\limits_{i=1}^{oud[x]}(dp[y]+edge[i])/oud[x]\)
正推:\(dp[i]\)表示从\(1\)到\(i\)的期望,\(g[i]\)表示从\(1\)到\(i\)的概率,方程的转移:对于一条从\(x\)到\(y\)的边
\(dp[y]=\sum\limits_{i=1}^{ind[y]}(dp[x]+edge[i]\times g[x])/oud[x]\)
why?
逆推:
\(E(y)=p_1x_1+p_2x_2+\cdots\cdots+p_nx_n\)
\(E(x)=p_1(x_1+w)+p_2(x_2+w)+\cdots\cdots+p_n(x_n+w)=E(y)+\sum\limits_{i=1}^np_i\times w=E(y)+w\)
因为从\(i\)到\(n\),所有概率和为\(1\)
正推:
\(E(x)=p_1x_1+p_2x_2+\cdots\cdots+p_nx_n\)
\(E(y)=p_1(x_1+w)+p_2(x_2+w)+\cdots\cdots+p_n(x_n+w)=E(x)+\sum\limits_{i=1}^np_i\times w\neq E(x)+w\)
因为从\(1\)到\(i\),所有概率和i不为1
CODE(正推):
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int MAXX=100010;
int oud[MAXX],ind[MAXX],ver[MAXX<<1],nxt[MAXX<<1],head[MAXX],edge[MAXX<<1];
double dp[MAXX],g[MAXX];
int tot,n,m;
inline void add(int x,int y,int z){
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
edge[tot]=z;
oud[x]++;
ind[y]++;
}
inline void topsort(){
queue<int>q;
for(int i=1;i<=n;++i)if(!ind[i])q.push(i);
dp[1]=0.000;
g[1]=1.000;
while(q.size()){
int x=q.front();
q.pop();
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
dp[y]+=(dp[x]+(double)edge[i]*g[x])/(double)oud[x];
g[y]+=g[x]/(double)oud[x];
if(--ind[y]==0)q.push(y);
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
topsort();
printf("%.2lf",dp[n]);
return 0;
}
CODE2(逆推 )为了方便更新我们建了反图,但是出度以原图为准
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int MAXX=100010;
int head[MAXX],ver[MAXX<<1],nxt[MAXX<<1],edge[MAXX<<1],ind[MAXX],oud[MAXX];
int tot,n,m;
double dp[MAXX];
inline void add(int x,int y,int z){
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
edge[tot]=z;
}
inline void topsort(){
queue<int>q;
dp[n]=0;
for(int i=1;i<=n;++i)if(!ind[i])q.push(i);
while(q.size()){
int x=q.front();
q.pop();
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
dp[y]+=(dp[x]+(double)edge[i])/(double)oud[y];
if(--ind[y]==0)q.push(y);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(y,x,z);
ind[x]++;
oud[x]++;
}
topsort();
printf("%0.2lf",dp[1]);
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· SQL Server统计信息更新会被阻塞或引起会话阻塞吗?
· 本地部署 DeepSeek:小白也能轻松搞定!
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
· 我们是如何解决abp身上的几个痛点
· 如何基于DeepSeek开展AI项目