Miraclys

一言(ヒトコト)

Luogu P4316 绿豆蛙的归宿

Luogu P4316 绿豆蛙的归宿

题目大意:

给定一个 DAG,求起点到终点的路径长度的期望。

貌似是这种概率题的一种套路,逆推。

我们设从起点到终点的路径上 \(f[i]\) 表示 \(i\) 点到达终点的期望路径长度,那么我们前一点总是可以由后一点的 \(f\) 状态推导而来。

所以我们可以得到: $$f[i] = \frac{\sum\limits_{i \to j} f[j] + w}{out[i]}$$

所以我们可以反向建边,拓扑,然后初始化 \(f[n] = 0\),输出 \(f[1]\) 即可。

代码:

using namespace std;

const int N = 1e5 + 5;
int n, m, cnt, head[N], in[N], deg[N];
double f[N];

struct Edge {
	int to, next;
	double w;
}e[N << 1];

inline int read() {
	int x = 0, f = 1;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-') f = -1;
		c = getchar();
	}
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
	return x * f;
}

inline void add(int x, int y, double z) {
	e[++cnt].to = y;
	e[cnt].next = head[x];
	e[cnt].w = z;
	head[x] = cnt;
}

int main() {
	n = read(), m = read();
	int x, y;
	double z;
	for (int i = 1; i <= m; ++i) {
		x = read(), y = read();
		scanf("%lf", &z);
		add(y, x, z);
		++in[x], ++deg[x];
	}
	f[n] = 0.0;
	queue <int> q;
	q.push(n);
	while (!q.empty()) {
		int top = q.front();
		q.pop();
		int to;
		for (int i = head[top]; i ; i = e[i].next) {
			to = e[i].to;
			f[to] = f[to] + (f[top] + e[i].w) / deg[to];
			if (--in[to] == 0) q.push(to);
		}
	}
	printf("%.2lf\n", f[1]);
	return 0;
} 
posted @ 2022-11-06 20:28  Miraclys  阅读(14)  评论(0编辑  收藏  举报

关于本博客样式

部分创意和图片借鉴了

BNDong

的博客,在此感谢