看到求方案数,应该很容易想到dp
f[u][i]表示到点u,且比到u的最短距离多i的方案数
那么需要先预处理dis数组,spfa或者堆优化的dijk
因为考虑到dp的顺序,f[u][i]转移到f[v][j]时,j不可能小于i
所以需要从0到k枚举i,然后从最后一个点开始记忆化搜索
至于判断0环,只需要在记忆化搜索的时候加一个栈即可
1A的代码,哈哈
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #define N 200001 using namespace std; int T, n, m, k, p, cnt, cnt1, ans; int head[N], to[N], nex[N], val[N], head1[N], to1[N], nex1[N], val1[N], f[N][51], dis[N]; bool flag, vis[N], vis1[N][51], ins[N][51]; queue <int> q; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * f; } inline void add(int x, int y, int z) { to[cnt] = y; val[cnt] = z; nex[cnt] = head[x]; head[x] = cnt++; } inline void add1(int x, int y, int z) { to1[cnt1] = y; val1[cnt1] = z; nex1[cnt1] = head1[x]; head1[x] = cnt1++; } inline void spfa() { int i, v, u; q.push(1); dis[1] = 0; while(!q.empty()) { u = q.front(); q.pop(); vis[u] = 0; for(i = head[u]; ~i; i = nex[i]) { v = to[i]; if(dis[v] > dis[u] + val[i]) { dis[v] = dis[u] + val[i]; if(!vis[v]) { q.push(v); vis[v] = 1; } } } } } inline void init() { int i, x, y, z; n = read(); m = read(); k = read(); p = read(); for(i = 1; i <= m; i++) { x = read(); y = read(); z = read(); add(x, y, z); add1(y, x, z); } spfa(); f[1][0] = 1; } inline void clear() { cnt = cnt1 = ans = flag = 0; memset(head, -1, sizeof(head)); memset(head1, -1, sizeof(head1)); memset(vis, 0, sizeof(vis)); memset(dis, 127, sizeof(dis)); memset(f, 0, sizeof(f)); memset(vis1, 0, sizeof(vis1)); memset(ins, 0, sizeof(ins)); } inline int dfs(int u, int i) { int j, v; if(i < 0 || flag) return 0; if(ins[u][i]) return flag = 1; if(vis1[u][i]) return f[u][i]; ins[u][i] = 1; for(j = head1[u]; ~j; j = nex1[j]) { v = to1[j]; f[u][i] = (f[u][i] + dfs(v, dis[u] + i - val1[j] - dis[v])) % p; } vis1[u][i] = 1; ins[u][i] = 0; return f[u][i]; } inline int solve() { int i, t; for(i = 0; i <= k; i++) { t = dfs(n, i); if(flag) return -1; ans = (ans + t) % p; } return ans; } int main() { T = read(); while(T--) { clear(); init(); printf("%d ", solve()); } return 0; }