• 洛谷4316 绿豆蛙的归宿(DAG递推/概率dp)


    题目大意:

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

    根据题意可以知道每一条边都有一定概率被走到

    那么(displaystyleegin{aligned} Ans = sum_{e in E} f_ew_eend{aligned}),其中(E)是边的集合,(f_e)是经过边(e)的期望次数,(w_e)是边(e)的边权

    这样我们只需要求经过每一条边的期望次数

    对于每一条边,经过这条边的期望次数就是经过这条边起点的期望次数除以这条边起点的出度

    这样我们就只需要求经过每一个点的期望次数

    由于是DAG,我们在DAG上拓扑排序递推一下即可

    在地推的过程中,我们可以顺便求出经过每条边的期望次数

    (其实经过某一个点的期望次数就等于它所有入边的期望次数的和,它所有出边的期望次数就等于它的期望次数除以它的出度)

    详见代码

    #include <cstdio>
    #include <iostream>
    
    using namespace std;
    
    struct edge
    {
    	int v, w, ne;
    }a[200010];
    
    int n, m, tmp, top;
    int in[100010], out[100010], h[100010], s[100010];
    double f[200010], p[100010], ans;
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for (int x, y, z, i = 1; i <= m; i++)
    	{
    		scanf("%d%d%d", &x, &y, &z);
    		a[++tmp] = (edge){y, z, h[x]};
    		h[x] = tmp;
    		out[x]++;
    		in[y]++;
    	}
    	s[++top] = 1;
    	p[1] = 1;
    	while (top > 0)//用一个栈维护所有可以选择的点
    	{
    		int x = s[top--];
    		for (int i = h[x]; i != 0; i = a[i].ne)
    		{
    			in[a[i].v]--;
    			p[a[i].v] += p[x] / out[x];//累加经过一个点的期望次数
    			f[i] = p[x] / out[x];//计算经过一个边的期望次数
    			if (in[a[i].v] == 0)
    				s[++top] = a[i].v;
    		}
    	}
    	for (int i = 1; i <= m; i++)
    		ans += f[i] * a[i].w;
    	printf("%.2f
    ", ans);
    	return 0;
    }
    

    拓展:如果不是DAG,可以列方程组求解,详见[HNOI2013]游走

  • 相关阅读:
    Hadoop实战课程
    R语言实战读书笔记(七)基本统计分析
    R语言实战读书笔记(六)基本图形
    python-unexpected content storage modification出错
    python——no module named XX
    R语言实战读书笔记(五)高级数据管理
    R语言缺失值信息处理
    R语言,NA,NAN
    R语言实战读书笔记(四)基本数据管理
    R语言实战读书笔记(三)图形初阶
  • 原文地址:https://www.cnblogs.com/oier/p/9596660.html
Copyright © 2020-2023  润新知