\(Description:\)
给出一个DAG,求出从1到n的期望路径长度,从一个点走每条边的概率相同
\(Sample\) \(Input:\)
4 4
1 2 1
1 3 2
2 3 3
3 4 4
\(Sample\) \(Output:\)
7.00
相对不太毒瘤的期望dp,设计dp方案:
设f[x]表示从x到终点的期望长度。
很明显f[n]=0,答案是f[1],那么怎么逆推捏?
很明显(怎么又明显了? :
\(f[x]=\sum_{i=0}^{k}(f[to[i]]+dis[i])*\frac{1}{k}\)
一种非常正常的想法是搜索,遍历整张图,答案就出来了。
我没写深搜,毕竟不知道怎么保证在计算当前点时,它连向的是否已经被更新结束
考虑反着拓扑的同时求出这个鬼玩意,因为拓扑可以保证只有对一个点更新完了才会入队让他去更新别的点。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,En;
const int N=1e5;
typedef double DD;
int indeg[N+5],outdeg[N+5];
int head[N+5];
struct edge {
int next,to,dis;
}E[(N<<1)+5];
DD dis[N+5];
inline void add(int from,int to,int dis){
E[++En].next=head[from];
E[En].to=to;
E[En].dis=dis;
head[from]=En;
}
inline void topsort(int s){
queue <int> q;
q.push(s);
dis[s]=0;
while(q.size()){
int u=q.front();q.pop();
for(int i=head[u];i;i=E[i].next){
int v=E[i].to;
dis[v]+=(DD)((dis[u]+E[i].dis)/indeg[v]);
outdeg[v]--;
if(!outdeg[v]) q.push(v);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int x=0,y=0,u=0;
scanf("%d%d%d",&x,&y,&u);
add(y,x,u);
outdeg[x]++;indeg[x]++;
}
topsort(n);
printf("%.2lf\n",dis[1]);
return 0;
}