- 2017
T3
- @ 2025-10-15 21:06:56
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int, int> PII;
const int N = 1e5 + 10, M = 4e5 + 10, K = 55;
int n, m, k, P;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];
int in_stk[N][K], inf;
int f[N][K];
void add(int a, int b, int c)
{
e[idx] = b; w[idx] = c;
ne[idx] = h[a]; h[a] = idx ++;
}
bool st[N];
void dij()
{
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, 1});
while(heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.y;
if(st[ver]) continue;
st[ver] = true;
for(int i = h[ver]; ~i; i = ne[i])
{
if(i & 1) continue; // 反向边不要
int j = e[i];
if(dist[j] > dist[ver] + w[i])
{
dist[j] = dist[ver] + w[i];
heap.push({dist[j], j});
}
}
}
}
int dp(int b, int y)
{
if(in_stk[b][y])
{
inf = true;
return 0;
}
int &v = f[b][y];
if(v != -1) return v;
in_stk[b][y] = true;
v = 0;
if(b == 1 && !y) v++;
for(int i = h[b]; ~i; i = ne[i])
{
if(!(i & 1)) continue;
int a = e[i];
int x = dist[b] + y - w[i] - dist[a];
if(x < 0 || x > k) continue;
v = (v + dp(a, x)) % P;
if(inf) return 0;
}
in_stk[b][y] = false;
return v;
}
int main()
{
int T;
cin >> T;
while(T --)
{
cin >> n >> m >> k >> P;
memset(h, -1, sizeof h);
idx = 0;
while(m --)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c), add(b,a , c);
}
dij();
memset(f, -1, sizeof f);
memset(in_stk, 0, sizeof in_stk);
inf = false;
int res = 0;
for(int i = 0; i <= k; i++)
{
res = (res + dp(n, i)) % P;
if(inf) break;
}
if(inf) res = -1;
cout << res << endl;
}
return 0;
}
/*
f(b, y)来表示从起点走到b,且路径长度恰好是y的所有路线的数量。
f(b, y) = f(a1, y-w1) + f(a2, y-w2) + ...
起点到终点最短路径为d[n], 那么f(b, y) 中y的取值范围应该是d[n] ~ d[n] + k;
请问普通点, 比如点b 是否也能满足f(b, d[b]), f(b, d[b] + k)
对于每个点b来说,只需要考虑满足d[b] <= y <= d(b) + k的y,这种y只有k+1
f(b, y) 表示从起点走到点b且长度恰好为d(b) + y的所有路线的数量
对于b的每个临点: x = db + y - wk - da
无穷多解: 某个点存在权值为0的环,且能到n,且起点能到这个点
即记忆化搜索时有循环依赖
*/
0 条评论
目前还没有评论...