1. 程式人生 > 其它 >DDoS(記憶化搜尋)

DDoS(記憶化搜尋)

題目:DDoS

題目連結:https://ac.nowcoder.com/acm/problem/201607

題意:有n個節點,m條邊,構成一個拓撲圖(有向無環圖)。求以節點1為起點,以節點n為終點的路徑數對20010905取模的結果。

輸入:第一行:兩個整數n,m。

接下來m行:每行三個整數x,y,z,表示節點x與y可以單向連線(x到y), 耗時為z。

資料滿足:3 <= n <= 100000, 1 <= m <= 200000, 0 <= z <= 10 ^ (pi * e)

pi為圓周率,e為自然常數。

輸出:輸出節點1到節點n的路徑數對20010905取模的結果。

樣例輸入:

4 4

1 2 3

1 3 1

2 4 1

3 4 3

樣例輸出:

2

樣例解釋:有兩條路徑(1 – 2 - 4), (1 – 3 - 4)。

題目分析:記憶化搜尋。

解題步驟:dp[i]的意義是節點i到n的路徑數。一個節點的dp值是它相鄰的節點的dp值之和,節點n的dp值為1。題目路徑數可能爆long long,注意取模。

建議讀一下原題,本題重點是對題意的理解,邊權給出的範圍有圓周率和自然常數也暗示著邊權沒有意義。

AC程式碼:

#include<iostream>

#include<vector>

using namespace std;

const int N = 1e5 + 10, M = 2e5 + 10, mod = 20010905;

vector<int> v[N];

int n, m;

long long f[N];

long long dfs(int x){

if(f[x] != 0) return f[x];

for(int i = 0;i < v[x].size();i++){

f[x] += dfs(v[x][i]);

}

return f[x];

}

void solve(){

scanf("%d %d", &n, &m);

f[n] = 1;

while(m--){

int x, y, z;

scanf("%d %d %d", &x, &y, &z);

v[x].push_back(y);

}

dfs(1);

f[1] %= mod;

printf("%lld\n", f[1]);

}

int main(void){

solve();

return 0;

}

時間複雜度:O(N + M)。

空間複雜度:O(N)。