题意:给出一个有向无环图,起点为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
",dis[1]);
return 0;
}