Luogu3953:逛公园
这题看上去想拿分层图做啊
f[x][k] 表示 到节点 x 走过的路程为 k + x的最短路 的方案数
然而只有六十分,因为判 0 环太暴力了 //好像应该有 70 ?
于是颓题解的记搜 //分层图的判 0 环似乎不是很可写
就大力搜索大力记忆化啊
判 0 环很神奇,不过跟两遍 spfa 的思路是差不多的,因为最短路树上不会去经过正权环
所以有环一定是 0 环
枚举到点 n 的距离和点 n 的最短路的差,倒着往回搜看会不会搜会当前状态,搜回来了就说明有 0 环
否则统计答案
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int MAXN = 100005, MAXM = 200005;
struct EDGE{
int nxt, to, val;
EDGE(int NXT = 0, int TO = 0, int VAL = 0) {nxt = NXT; to = TO; val = VAL;}
}edge[MAXM << 1];
int t, n, m, k, totedge;
int head[MAXN][2], dst[MAXN], vis[MAXN][55];
ll p, f[MAXN][55], ans;
bool vs[MAXN], ins[MAXN][55], fns[MAXN][55], GG;
priority_queue<pair<int,int> > q1;
inline int rd() {
register int x = 0;
register char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) {
x = x * 10 + (c ^ 48);
c = getchar();
}
return x;
}
inline void add(int x, int y, int v, int rev) {
edge[++totedge] = EDGE(head[x][rev], y, v);
head[x][rev] = totedge;
return;
}
inline void dij() {
dst[1] = 0;
q1.push(make_pair(0, 1));
while(!q1.empty()) {
int x = q1.top().second; q1.pop();
if(vs[x]) continue;
vs[x] = true;
for(int i = head[x][0]; i; i = edge[i].nxt) {
int y = edge[i].to;
if(dst[y] > dst[x] + edge[i].val) {
dst[y] = dst[x] + edge[i].val;
q1.push(make_pair(-dst[y], y));
}
}
}
ans = 0ll;
return;
}
int dfs(int x, int dlt) {
if(ins[x][dlt]) {
GG = true;
return f[x][dlt] = -1;
}
if(fns[x][dlt]) return f[x][dlt];
ins[x][dlt] = true;
for(int i = head[x][1]; i; i = edge[i].nxt) {
int y = edge[i].to, dlty = dst[x] + dlt - edge[i].val - dst[y];
if(0 <= dlty && dlty <= k) f[x][dlt] = (f[x][dlt] + dfs(y, dlty)) % p;
}
fns[x][dlt] = true;
ins[x][dlt] = false;
return f[x][dlt];
}
inline void clearall() {
totedge = 0; GG = false;
for(int i = 1; i <= n; ++i) {
head[i][0] = head[i][1] = 0;
vs[i] = false;
for(int j = 0; j <= 50; ++j) {
f[i][j] = 0ll;
fns[i][j] = ins[i][j] = false;
vis[i][j] = 0;
}
}
return;
}
int main() {
t = rd();
while(t--) {
n = rd(); m = rd(); k = rd(); p = (ll)rd();
register int xx, yy, vv;
for(int i = 1; i <= m; ++i) {
xx = rd(); yy = rd(); vv = rd();
add(xx, yy, vv, 0); add(yy, xx, vv, 1);
}
for(int i = 1; i <= n; ++i) dst[i] = 0x3f3f3f3f;
dij();
f[1][0] = 1ll;
for(int i = 0; i <= k; ++i) ans = (ans + dfs(n, i)) % p;
printf("%lld\n", GG ? -1 : ans);
clearall();
}
return 0;
}
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/

浙公网安备 33010602011771号