1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
| #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring>
typedef long long LL;
const int N = 1e5 + 5; const int M = 2e5 + 5; const int K_MAX = 50 + 5; const LL LLINF = 0x3f3f3f3f3f3f3f3fLL;
int n, m, K, mod; struct Graph { struct Edge { int to, nxt; LL w; } edge[M << 1]; int head[N], ek; void clear() { memset(head, 0, sizeof(head)); ek = 1; } void add_edge(int u, int v, LL w) { edge[ek] = (Edge){v, head[u], w}, head[u] = ek++; } } G, R, DAG;
LL dis1[N], disn[N]; void dijkstra(Graph Graph, LL *dis, int st) { std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> q; for(int i = 1; i <= n; i++) dis[i] = LLINF; dis[st] = 0; q.push({0, st}); while(!q.empty()) { auto p = q.top(); int u = p.second, d = p.first; q.pop(); if(dis[u] != d) continue; for(int i = Graph.head[u]; i; i = Graph.edge[i].nxt) if(dis[u] + Graph.edge[i].w < dis[Graph.edge[i].to]) { int v = Graph.edge[i].to; dis[v] = dis[u] + Graph.edge[i].w; q.push({dis[v], v}); } } }
bool exist[N]; void build_DAG() { for(int i = 1; i <= n; i++) exist[i] = true; for(int i = 1; i <= n; i++) if(dis1[i] + disn[i] > dis1[n] + K) exist[i] = false; for(int u = 1; u <= n; u++) if(exist[u]) for(int i = G.head[u]; i; i = G.edge[i].nxt) { int v = G.edge[i].to; if(!exist[v]) continue; if(dis1[v] == dis1[u] + G.edge[i].w) DAG.add_edge(u, v, G.edge[i].w); } }
int ind[N]; std::vector<int> order; bool check() { order.clear(); int cnt = 0; for(int i = 1; i <= n; i++) ind[i] = 0; std::vector<int> q; for(int u = 1; u <= n; u++) for(int i = DAG.head[u]; i; i = DAG.edge[i].nxt) { int v = DAG.edge[i].to; ind[v]++; } for(int i = 1; i <= n; i++) if(!ind[i]) q.push_back(i), cnt++, order.push_back(i); while(!q.empty()) { int u = q.back(); q.pop_back(); for(int i = DAG.head[u]; i; i = DAG.edge[i].nxt) { int v = DAG.edge[i].to; if(ind[v]) { ind[v]--; if(ind[v] == 0) q.push_back(v), cnt++, order.push_back(v); } } } return cnt == n; }
int f[N][K_MAX]; int dp() { for(int i = 1; i <= n; i++) for(int j = 0; j <= K; j++) f[i][j] = 0; f[1][0] = 1; for(int j = 0; j <= K; j++) { for(int i = 0; i < n; i++) { int u = order[i]; for(int k = DAG.head[u]; k; k = DAG.edge[k].nxt) { int v = DAG.edge[k].to; (f[v][j] += f[u][j]) %= mod; } } for(int u = 1; u <= n; u++) for(int i = G.head[u]; i; i = G.edge[i].nxt) { int v = G.edge[i].to; if(dis1[v] == dis1[u] + G.edge[i].w) continue; int tmp = dis1[u] + j + G.edge[i].w - dis1[v]; if(tmp <= K) (f[v][tmp] += f[u][j]) %= mod; } } int ans = 0; for(int j = 0; j <= K; j++) (ans += f[n][j]) %= mod; return ans; }
int main() { int T; scanf("%d", &T); while(T--) { G.clear(), R.clear(), DAG.clear(); scanf("%d%d%d%d", &n, &m, &K, &mod); for(int i = 1; i <= m; i++) { int u, v; LL w; scanf("%d%d%lld", &u, &v, &w); G.add_edge(u, v, w); R.add_edge(v, u, w); } dijkstra(G, dis1, 1), dijkstra(R, disn, n); build_DAG(); if(!check()) { puts("-1"); continue; } printf("%d\n", dp()); } return 0; }
|