[题解] 绿豆蛙的归宿

绿豆蛙的归宿


一个我不知道的神奇blog宠物,去他喵的

解法:拓扑排序 + 数学期望


对于数学期望,紫书给出的定义如下:

随机变量 X 的数学期望 EX 就是所有可能值按照概率加权的和

所以只要建好图就行了不知道它是怎么变蓝的,之后我们对其进行两种类型的选择性操作:

1.逆推

设对于结点 i,f[ i ]定义为从当前结点 i 出发到终点n 的数学期望,易得到f[ n ] = 0。
对于一条有向边(u , v),f[ u ] = sigma (f[ v ]+e[ i ].w)/out[ u ],反向建图拓扑排序即可,不再赘述。但是这里有一个细节:当前结点到达 n 结点,所有的概率和为一,所以不用再考虑概率的问题。代码如下:

#include <iostream>
#include <queue>
#include <cstdio>
#define re register
using namespace std;
const int maxn = 1e5 + 5;
int head[maxn],ru[maxn],deg[maxn],cnt = 0;
double f[maxn];
struct edge{
	int to,next,w;
}e[maxn*2];
inline void link(int u,int v,int w){
	e[++cnt].to=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;
	ru[v]++;deg[v]++;
}
int n,m;
inline void tuo_sort(){
	queue<int> q;
	q.push(n);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(re int i=head[u];i;i=e[i].next){
			int v=e[i].to;
			f[v]+=(f[u]+e[i].w)/deg[v];
			if(--ru[v]==0)q.push(v);
		}
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(re int i=1;i<=m;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		link(v,u,w);
	}
	f[n]=0.0;
	tuo_sort();
	printf("%.2lf",f[1]);
	return 0;
}

2.正推:

因为从1到i的概率和不一定是1,所以我们需要预处理概率问题,其他类似

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]*g[x]+(double)edge[i]*g[x])/(double)oud[x];
            g[y]+=g[x]/(double)oud[x];
            if(--ind[y]==0)q.push(y);
	} 
}
posted @ 2021-08-12 16:19  ¶凉笙  阅读(10)  评论(0编辑  收藏  举报