• 绿豆蛙的归宿


    两种方法,正推和逆推

    逆推:(dp[i])表示从(i)(n)的期望,方程的转移:对于一条从(x)(y)

    (dp[x]=sumlimits_{i=1}^{oud[x]}(dp[y]+edge[i])/oud[x])

    正推:(dp[i])表示从(1)(i)的期望,(g[i])表示从(1)(i)的概率,方程的转移:对于一条从(x)(y)的边

    (dp[y]=sumlimits_{i=1}^{ind[y]}(dp[x]+edge[i] imes g[x])/oud[x])

    why?

    逆推:

    (E(y)=p_1x_1+p_2x_2+cdotscdots+p_nx_n)

    (E(x)=p_1(x_1+w)+p_2(x_2+w)+cdotscdots+p_n(x_n+w)=E(y)+sumlimits_{i=1}^np_i imes w=E(y)+w)

    因为从(i)(n),所有概率和为(1)

    正推:

    (E(x)=p_1x_1+p_2x_2+cdotscdots+p_nx_n)

    (E(y)=p_1(x_1+w)+p_2(x_2+w)+cdotscdots+p_n(x_n+w)=E(x)+sumlimits_{i=1}^np_i imes w eq E(x)+w)

    因为从(1)(i),所有概率和i不为1

    CODE(正推):

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    using namespace std;
    const int MAXX=100010;
    int oud[MAXX],ind[MAXX],ver[MAXX<<1],nxt[MAXX<<1],head[MAXX],edge[MAXX<<1];
    double dp[MAXX],g[MAXX];
    int tot,n,m;
    inline void add(int x,int y,int z){
    	ver[++tot]=y;
    	nxt[tot]=head[x];
    	head[x]=tot;
    	edge[tot]=z;
    	oud[x]++;
    	ind[y]++;
    }
    inline void topsort(){
    	queue<int>q;
    	for(int i=1;i<=n;++i)if(!ind[i])q.push(i);
    	dp[1]=0.000;
        g[1]=1.000;
    	while(q.size()){
    		int x=q.front();
    		q.pop();
    		for(int i=head[x];i;i=nxt[i]){
    			int y=ver[i];
                dp[y]+=(dp[x]+(double)edge[i]*g[x])/(double)oud[x];
                g[y]+=g[x]/(double)oud[x];
                if(--ind[y]==0)q.push(y);
    		} 
    	}
    }
    int main(){
       cin>>n>>m;
       for(int i=1;i<=m;++i){
       	int x,y,z;
       	scanf("%d%d%d",&x,&y,&z);
       	add(x,y,z);
       }
       topsort();
       printf("%.2lf",dp[n]);
       return 0;
    }
    

    CODE2(逆推 )为了方便更新我们建了反图,但是出度以原图为准

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    using namespace std;
    const int MAXX=100010;
    int head[MAXX],ver[MAXX<<1],nxt[MAXX<<1],edge[MAXX<<1],ind[MAXX],oud[MAXX];
    int tot,n,m;
    double dp[MAXX];
    inline void add(int x,int y,int z){
    	ver[++tot]=y;
    	nxt[tot]=head[x];
    	head[x]=tot;
    	edge[tot]=z;
    }
    inline void topsort(){
    	queue<int>q;
    	dp[n]=0;
    	for(int i=1;i<=n;++i)if(!ind[i])q.push(i);
    	while(q.size()){
    		int x=q.front();
    		q.pop();
    		for(int i=head[x];i;i=nxt[i]){
    			int y=ver[i];
    			dp[y]+=(dp[x]+(double)edge[i])/(double)oud[y];
    			if(--ind[y]==0)q.push(y);
    		}
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;++i){
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		add(y,x,z);
    		ind[x]++;
    		oud[x]++;
    	}
    	topsort();
    	printf("%0.2lf",dp[1]);
    	return 0;
    }
    
  • 相关阅读:
    docker基础:docker网络模式
    WEB架构师成长之路之一-走正确的路(转载)
    DDD(领域驱动设计)
    C#泛型和泛型约束(转载)
    MES系统介绍
    vue中 computed和watch的一些简单理解(区别)(转载)
    sqlserver常用表值函数
    SQLServerAgent 当前未运行,因此无法将此操作通知它。
    浅谈敏捷开发(转载)
    认证、授权、鉴权和权限控制(转载)
  • 原文地址:https://www.cnblogs.com/ARTlover/p/9544518.html
Copyright © 2020-2023  润新知