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


    题目←

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

    [E[f] = sum_{ein 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可能被经过的次数
    (ein 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);
    }
    
  • 相关阅读:
    javascript中数组去重的4种方法
    dede使用方法----实现英文版的搜索功能
    dede去掉当前位置position后面的箭头
    dede使用方法----如何转换时间戳
    Python字符串、元组、列表、字典互相转换的方法
    Python 列表的操作
    Python 元祖的操作
    Python 操作文件、文件夹、目录大全
    python文件目录操作大全
    python用time函数计算程序运行时间
  • 原文地址:https://www.cnblogs.com/loi-pingxing/p/7782281.html
Copyright © 2020-2023  润新知