逆拓撲+dp

背景

隨着新版百度空間的上線,Blog寵物綠豆蛙完成了它的使命,去尋找它新的歸宿。

描述

給出一個有向無環圖,起點爲1終點爲N,每條邊都有一個長度,並且從起點出發能夠到達所有的點,所有的點也都能夠到達終點。綠豆蛙從起點出發,走向終點。
到達每一個頂點時,如果有K條離開該點的道路,綠豆蛙可以選擇任意一條道路離開該點,並且走向每條路的概率爲 1/K 。
現在綠豆蛙想知道,從起點走到終點的所經過的路徑總長度期望是多少?

輸入格式

第一行: 兩個整數 N M,代表圖中有N個點、M條邊
第二行到第 1+M 行: 每行3個整數 a b c,代表從a到b有一條長度爲c的有向邊

輸出格式

從起點到終點路徑總長度的期望值,四捨五入保留兩位小數。

測試樣例1

輸入

4 4 
1 2 1 
1 3 2 
2 3 3 
3 4 4

輸出

7.00

此題用記憶化會爆棧,故需要逆拓撲後,進行dp。

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

struct edge{
    int to,w,next;
}p[200010];
int tot,n;
int head[100010];
void addedge(int a,int b,int c){
    p[tot].to=b;
    p[tot].w=c;
    p[tot].next=head[a];
    head[a]=tot++;
}
double dp[100010];
int out[100010],q[100010];
int out1[100010];
int main()
{
    int m,a,b,c;
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof head);
    while(m--){
        scanf("%d%d%d",&a,&b,&c);
        addedge(b,a,c);
        out[a]=++out1[a];
    }
    int s=0,e=-1;
    q[++e]=n;
    while(s<=e){
        int u=q[s++];
        for(int i=head[u];i!=-1;i=p[i].next){
            int v=p[i].to;
            dp[v]+=(dp[u]+p[i].w)/out[v];
            if(--out1[v]==0) q[++e]=v;
        }
    }
    printf("%.2f\n",dp[1]);
    return 0;
}




























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章