【bzoj3036】绿豆蛙的归宿——期望dp
Description
随着新版百度空间的下线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿。
给出一个有向无环的连通图,起点为1终点为N,每条边都有一个长度。绿豆蛙从起点出发,走向终点。
到达每一个顶点时,如果有K条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为 1/K 。
现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?
Input
第一行: 两个整数 N M,代表图中有N个点、M条边
第二行到第 1+M 行: 每行3个整数 a b c,代表从a到b有一条长度为c的有向边
Output
从起点到终点路径总长度的期望值,四舍五入保留两位小数。
Sample Input
4 4
1 2 1
1 3 2
2 3 3
3 4 4
1 2 1
1 3 2
2 3 3
3 4 4
Sample Output
7.00
HINT
对于100%的数据 N<=100000,M<=2*N
因为是DAG所以直接dfs,每次统计答案并更新概率就行了。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define mem(a,p) memset(a,p,sizeof(a)) 5 typedef double Cu; 6 const int N=1e5+10; 7 struct node{int ne,to,w;}e[N*2]; 8 int n,m,first[N],tot=0,count[N]; 9 int read(){ 10 int ans=0,f=1;char c=getchar(); 11 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 12 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 13 return ans*f; 14 } 15 Cu ans=0; 16 void ins(int u,int v,int w){count[u]++;e[++tot]=(node){first[u],v,w};first[u]=tot;} 17 void dfs(int x,int fa,Cu pp){ 18 for(int i=first[x];i;i=e[i].ne){ 19 int to=e[i].to; 20 if(to==fa)continue; 21 Cu p=pp*1.0/count[x]; 22 ans+=p*e[i].w;dfs(to,x,p); 23 } 24 } 25 int main(){ 26 n=read();m=read(); 27 for(int i=1,a,b,c;i<=n;i++){ 28 a=read();b=read();c=read();ins(a,b,c); 29 } 30 dfs(1,0,1); 31 printf("%.2lf",ans); 32 return 0; 33 }