一、题目:
二、思路:
记忆化搜索。
首先,用SPFA预处理最短路。
设
f[u][k]
f
[
u
]
[
k
]
表示从起点到u节点比最短路长k的路径总数,则显然有
f[u][k]=∑vv∈u的前驱f[v][dis[u]+k−w−dis[v]]
f
[
u
]
[
k
]
=
∑
v
v
∈
u
的
前
驱
f
[
v
]
[
d
i
s
[
u
]
+
k
−
w
−
d
i
s
[
v
]
]
其中dis数组记录最短路,w为从v到u的边的长度。
初始化:f[1][0]=1。
判0环:bool数组 c[u][k] c [ u ] [ k ] 记录是否搜到(u,k),如果第二次搜到(u,k),有0环。
注意取模。
三、代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
inline int read(void){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
const int maxn=100005,maxm=200005,maxk=55;
int T,n,m,K,P,head[maxn],tot,Head[maxn],dis[maxn],f[maxn][maxk];
bool inq[maxn],c[maxn][maxk],ff;
struct Edge{
int y,next,w;
}e[maxm],E[maxm];
inline void connect(int x,int y,int w){
e[++tot]=(Edge){y,head[x],w};
head[x]=tot;
E[tot]=(Edge){x,Head[y],w};
Head[y]=tot;
}
inline void init(void){
n=read();m=read();K=read();P=read();
for(register int i=1;i<=m;i++){
int x=read(),y=read(),w=read();
connect(x,y,w);
}
return;
}
inline void spfa(void){
queue<int>q;q.push(1);
memset(dis,0x3f,sizeof(dis));dis[1]=0;
inq[1]=true;
while(q.size()){
int u=q.front();q.pop();inq[u]=false;
for(register int i=head[u];i;i=e[i].next){
int v=e[i].y;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!inq[v]){
q.push(v);
inq[v]=true;
}
}
}
}
return;
}
inline int dfs(int u,int k){
if(~f[u][k])return f[u][k];
c[u][k]=true;
f[u][k]=0;
for(register int i=Head[u];i;i=E[i].next){
int v=E[i].y;
int t=dis[u]+k-E[i].w-dis[v];
if(t<0)continue;
if(c[v][t]){ff=true;}
f[u][k]+=dfs(v,t),f[u][k]%=P;
}
c[u][k]=false;
return f[u][k];
}
inline void clear(void){
tot=n=m=K=P=0;
memset(head,0,sizeof(head));
memset(Head,0,sizeof(Head));
memset(dis,0,sizeof(dis));
memset(f,-1,sizeof(f));
memset(inq,false,sizeof(inq));
memset(c,false,sizeof(c));
memset(e,0,sizeof(e));
memset(E,0,sizeof(E));
ff=false;
return;
}
inline void solve(void){
spfa();
int ans=0;
f[1][0]=1;
for(register int j=0;j<=K;j++){
ans+=dfs(n,j);ans%=P;
}
dfs(n,K+1);
if(ff){puts("-1");return;}
printf("%d\n",ans%P);
return;
}
int main(){
T=read();
while(T--){
clear();
init();
solve();
}
return 0;
}