Title Description
Policy-making students especially like the park. Park can be seen as an N points have sides forming the M to FIG, loopback and without heavy side. Wherein . 1 dot is an inlet park, N dot export park, each side has a non-negative weight value that represents the policy plan after this time it will take sides.
Policy-making will go to the park every day, he was always the one to go dot, from N out of the dot.
Policy-making like new things, he does not want the park for two days exactly the same route, while making policy or a particular love for the boy to learn, every day he does not want to spend too much time in the park on this matter. If . 1 point number to N dots of the shortest length d, then the policy strategy will prefer a length not exceeding d + K route.
Policy-making students want to know how many routes to meet the conditions of the total, can you help him?
To avoid excessive output, the answer to the P modulo.
If there are an infinite number of legitimate route, output -1 .
Input Format
The first row contains an integer T , represents the number of data sets.
Next T sets of data, for each set of data:
The first row contains four integers N, M, K, P separated by a space between each of the two integers.
Next M rows, each row of three integers A I , B I , C I , the representative number A I , B I has a weight of between one point C I directed edge, each separated by a space between two integers.
Output Format
Output file contains T lines, each integer represents the answer.
A closer look at this question can be found to be a DP although I did not see it test , first find the shortest path to either 1 point (Dijkstra, SPFA, Floyd later) start d (on) p (shoot), sub-state dp [u] [k] from the representative node u to node No. 1 is the path length DIS [u] (u 1 to the shortest) + k is the number of paths,
Transfer equation: Σdp [v] [dis [u] - dis [v] + k - edge (u, v)] (dfs anti FIG run, seeking dp [n] [0 ~ k]), and then judged what has there is no "0" ring can be.
On the code:
#include <iostream> #include <queue> #include <cstring> using namespace std; const int MAX = 1e5 + 10; struct node{ int pre, to, val; }edge[2 * MAX]; int head[MAX], tot; int dis[MAX], dp[MAX][51]; bool vis[MAX], vis2[MAX][51]; int a[2 * MAX], b[2 * MAX], c[2 * MAX]; int T, n, m, k, p, ans; bool zero; void insert(int u, int v, int len) { edge[++tot] = node{head[u], v, len}; head[u] = tot; } int read() { int ret = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) ret = ret * 10 + ch - '0', ch = getchar(); return ret; } priority_queue<pair<int, int> > q; void dijkstra() { memset(dis, 0x3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); dis[1] = 0; q.push(make_pair(0, 1)); while (!q.empty()) { int x = q.top().second; q.pop(); if (vis[x]) continue; vis[x] = 1; for (int i = head[x]; i; i = edge[i].pre) { int y = edge[i].to, z = edge[i].val; if (dis[y] > dis[x] + z) { dis[y] = dis[x] + z; q.push(make_pair(-dis[y], y)); } } } } int dfs(int x, int now_k) { if (dp[x][now_k] != -1) return dp[x][now_k]; vis2[x][now_k] = 1; dp[x][now_k] = 0; for (int i = head[x]; i; i = edge[i].pre) { int y = edge[i].to, z = edge[i].val; int next_k = dis[x] - dis[y] + now_k - z; if (next_k < 0) continue; if (vis2[y][next_k]) zero = 1; dp[x][now_k] += dfs(y, next_k); //cout << dp[x][now_k] << endl; if (dp[x][now_k] > p) dp[x][now_k] -= p; } vis2[x][now_k] = 0; return dp[x][now_k]; } int main() { T = read(); while (T--) { memset(head, 0, sizeof(head)); memset(dp, -1, sizeof(dp)); memset(vis2, 0, sizeof(vis2)); tot = 0; ans = 0; zero = 0; n = read(), m = read(), k = read(), p = read(); for (int i = 1; i <= m; i++) { a[i] = read(), b[i] = read(), c[i] = read(); insert(a[i], b[i], c[i]); } dijkstra(); memset(head, 0, sizeof(head)); tot = 0; for (int i = 1; i <= m; i++) { insert(b[i], a[i], c[i]); } dp[1][0] = 1; for (int i = 0; i <= k; i++) { ans += dfs(n, i); //puts(""); if (ans > p) ans -= p; } dfs(n, k + 1); if (zero) { puts("-1"); continue; } cout << ans << "\n"; } return 0; }