[codevs2488]绿豆蛙的归宿 概率与期望

题目←

思路:
求距终点距离的递推式:
dis[f] = dis[t] + l[i].v
加上期望
E[f] = E[t] +l[i].v
这是对于f只有t一条出边的情况
多条出边时,设G为f所有出边的集合

\[E[f] = \sum_{e\in G}\frac{E[e.t] + e.v}{out[f]} \]

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
double E[200000];
int n,m;
struct edge{
	int f,t;
	double v;
}l[200000 << 1];
int head[200000],next[400000],tot;
void init(int n){
	for(int i = 1;i <= n;i ++){
		head[i] = -1;
	}
}
void build(int f,int t,double v){
	l[++tot] = (edge){f,t,v};
	next[tot] = head[f];
	head[f] = tot;
}
int a,b;
double c;
int ru[200000],topo[200000],chu[200000];
int hd,tl;
int main(){
	scanf("%d%d",&n,&m);
	init(n);
	for(int i = 1;i <= m;i ++){
		scanf("%d%d%lf",&a,&b,&c);
		build(a,b,c);
		ru[b] ++;
		chu[a] ++;
	}
	for(int i = 1;i <= n;i ++){
		if(!ru[i]){
			topo[tl ++] = i;
		}
	}
	while(hd != tl){
		int u = topo[hd];
		hd ++;
		for(int i = head[u];i != -1;i = next[i]){
			int t = l[i].t;
			ru[t] --;
			if(!ru[t]){
				topo[tl ++] = t;
			}
		}
	}
	for(int i = n - 1;i >= 0;i --){
		int u = topo[i];
		if(head[u] == -1)continue;
		for(int j = head[u];j != -1;j = next[j]){
			int t = l[j].t;
			E[u] += (E[t] + l[j].v)/chu[u];
		}
	}
	printf("%.2lf",E[1]);
}

注意最后不会到达n的边也是对答案有贡献的(可能被走过)


又看了某大佬的解法……分别计算每条边对答案的贡献
dp[f]->f可能被经过的次数
\(e\in G_{f}\),则e对答案贡献为$$\frac{dp[f] * e.v} {out[f]}$$
dp[t]可由\(\sum{dp[f]}\)推来

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
double E[200000];
int n,m;
struct edge{
	int f,t;
	double v;
}l[200000 << 1];
int head[200000],next[400000],tot;
void init(int n){
	for(int i = 1;i <= n;i ++){
		head[i] = -1;
	}
}
void build(int f,int t,double v){
	l[++tot] = (edge){f,t,v};
	next[tot] = head[f];
	head[f] = tot;
}
int a,b;
double c;
int ru[200000],topo[200000],chu[200000];
int hd,tl;
double ans;
int main(){
	scanf("%d%d",&n,&m);
	init(n);
	for(int i = 1;i <= m;i ++){
		scanf("%d%d%lf",&a,&b,&c);
		build(a,b,c);
		ru[b] ++;
		chu[a] ++;
	}
	for(int i = 1;i <= n;i ++){
		if(!ru[i]){
			topo[tl ++] = i;
		}
	}
	E[1] = 1.00;
	while(hd != tl){
		int u = topo[hd];
		hd ++;
		for(int i = head[u];i != -1;i = next[i]){
			int t = l[i].t;
			ru[t] --;
			E[t] += E[u]/chu[u];
			ans += E[u]*l[i].v/chu[u];
			if(!ru[t]){
				topo[tl ++] = t;
			}
		}
	}
	printf("%.2lf",ans);
}
posted @ 2017-11-04 09:31  _平行  阅读(109)  评论(0编辑  收藏  举报