绿豆蛙的归宿

洛咕

题意:给出一个有向无环图,起点为1终点为N,每条边都有一个长度,并且从起点出发能够到达所有的点,所有的点也都能够到达终点.绿豆蛙从起点出发,走向终点.到达每一个顶点时,如果有K条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为1/K.现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?

分析:设\(dis[x]\)表示\(x\)点到终点的期望值,显然有\(dis[n]=0\),我们最后要求的就是\(dis[1]\),设\(in[x]\)\(out[x]\)分别表示x点入度和出度,则有\(dis[v]=\sum (dis[u]+w[u][v])/in[v]\).因为是有向无环图,所以可以直接根据出度是否为0来拓扑排序.

因为我们已知的是终点的状态\(dis[n]=0\),要求\(dis[1]\),所以考虑反向建边,从终点向起点转移.

#include<bits/stdc++.h>
using namespace std;
inline int read(){
   int s=0,w=1;char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
   return s*w;
}
const int N=100005;
int in[N],out[N];double dis[N];
int tot,head[N],nxt[N*2],to[N*2],w[N*2];
queue<int> q;
inline void add(int a,int b,int c){
	nxt[++tot]=head[a];head[a]=tot;
    to[tot]=b;w[tot]=c;
}
int main(){
    int n=read(),m=read();
    for(int i=1;i<=m;i++){
		int x=read(),y=read(),z=read();
		add(y,x,z);//反向建边
        out[x]++;in[x]++;//统计入度和出度
    }
    q.push(n);
    while(q.size()){
		int u=q.front();q.pop();
		for(int i=head[u];i;i=nxt[i]){
	    	int v=to[i];
	    	dis[v]+=(dis[u]+w[i])*1.0/in[v];//计算概率期望
	    	out[v]--;if(out[v]==0)q.push(v);//拓扑排序
		}
    }
    printf("%.2lf\n",dis[1]);
    return 0;
}

posted on 2019-05-04 16:55  PPXppx  阅读(119)  评论(0编辑  收藏  举报