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)。

posted @ 2021-10-16 22:58  思丶君  阅读(52)  评论(0)    收藏  举报