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

浙公网安备 33010602011771号