Saito Asuka saiko!!!

有些走累了呢 有些走累了呢 虽然以那麼平凡的表现 来形容人生的漫长道路 想稍稍休息下呢 想稍稍休息下呢 时间每分每刻都这样残酷 将我紧拖著前行...

luogu P4316 绿豆蛙的归宿|数论|数学期望|图论|拓扑排序

luogu P4316 绿豆蛙的归宿|数论|数学期望|图论|拓扑排序

Problem

Problem


分析

数论部分

数学期望:

F[x]表示从节点x走到终点所经过的路径的期望长度。
若从x出发有k条边,分别到达y1,y2,y3,...,yk,边长分别为z1,z2,...,zk

则根据数学期望的定义

\[E\left ( X \right )= \sum P_i X_i,其中P_i表示发生该离散型随机事件概率,X_i表示随机变量取值 \]

以及数学期望的线性性质:

\[E\left ( X+Y \right )=E\left ( X \right )+E\left ( Y \right ) \]

得到:

\[F\left [ X \right ]=\frac{1}{k}\sum \begin{matrix} k\\ i=1 \end{matrix} \left ( F\left [ y_i \right ]+z_i \right) \]

Code

F[v]+=(F[u]+w)/k[v];


图论部分:

拓扑排序:

显然,F[n]=0,求F[1]。
所以对反向图进行拓扑排序。
拓扑排序步骤:
先统计所有节点的入度
对于入度为0的节点就分离出来
把这个节点指向的节点入度-1
一直做修改,直到所有的节点都被分离出来
判断无解:
最后不存在入度为0的节点。

Code

void toposort(){
	queue<int> q;q.push(n);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=0;i<g[u].size();i++){
			int v=g[u][i].v,w=g[u][i].w;
			F[v]+=(F[u]+w)/k[v];
			if(rd[v]) rd[v]--;
			if(rd[v]==0) q.push(v);
		}
	}
}

Code

#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
void read(int &n){
	int num=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		num=num*10+ch-'0';
		ch=getchar();
	}
	n=num*w;
}
const int maxn=100005;
struct node{int v,w;};
vector<node> g[maxn];
int n,m,rd[maxn],k[maxn];double F[maxn];
void toposort(){
	queue<int> q;q.push(n);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=0;i<g[u].size();i++){
			int v=g[u][i].v,w=g[u][i].w;
			F[v]+=(F[u]+w)/k[v];
			if(rd[v]) rd[v]--;
			if(rd[v]==0) q.push(v);
		}
	}
}
int main(){
	read(n);read(m);
	for(int i=1;i<=m;i++){
		int a,b,c;read(a);read(b);read(c);
		g[b].push_back((node){a,c});//建反图 
		rd[a]++;k[a]++;
	}
	toposort(); 
	printf("%.2lf",F[1]);
	return 0;
}
posted @ 2019-01-30 12:12  斋藤飞鸟  阅读(367)  评论(6编辑  收藏  举报
动画加载完毕