版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83833908
传送门
解析:
首先这鬼畜的最短路肯定你是要自己跑一遍的。
但是我是在反图上面跑。。
因为我的DP策略表示在当前点 剩余冤枉路可以走 走到终点的方案数,所以我需要的是每个点到终点的最短路,起点…不重要。
然后就直接这样子记忆化搜索一下就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=100005,M=200005;
int last[N],nxt[M],to[M],ecnt;
int w[M];
inline void addedge(int u,int v,int val){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
}
int dist[N];
namespace REV_GRAPH{
int last[N],nxt[M],to[M],ecnt;
int w[M];
inline void addedge(int u,int v,int val){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
}
set<pair<int,int> > q;
inline void Dij(int S){
memset(dist,0x3f,sizeof dist);
dist[S]=0;
q.insert(make_pair(0,S));
while(!q.empty()){
int u=q.begin()->second;
q.erase(q.begin());
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
if(dist[v]>dist[u]+w[e]){
q.erase(make_pair(dist[v],v));
dist[v]=dist[u]+w[e];
q.insert(make_pair(dist[v],v));
}
}
}
}
inline void clear(){
memset(last,0,sizeof last);ecnt=0;
}
}
int f[N][52];
bool vis[N][52];
bool flag;
inline void clear(){
memset(last,0,sizeof last);ecnt=0;
memset(f,-1,sizeof f);
memset(vis,0,sizeof vis);
REV_GRAPH::clear();
flag=true;
}
int n,m,k,mod;
inline int dfs(int u,int rest){
if(vis[u][rest]){
flag=false;
return 0;
}
if(~f[u][rest])return f[u][rest];
vis[u][rest]=true;
int res=0;
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
int tmp=rest-(dist[v]+w[e]-dist[u]);
if(tmp<0)continue;
res=(res+dfs(v,tmp))%mod;
if(!flag)return 0;
}
if(n==u&&rest==0)res=1;
vis[u][rest]=false;
return f[u][rest]=res;
}
int T;
signed main(){
T=getint();
while(T--){
n=getint();m=getint();k=getint();mod=getint();
clear();
for(int re i=1;i<=m;++i){
int u=getint(),v=getint(),val=getint();
addedge(u,v,val);
REV_GRAPH::addedge(v,u,val);
}
REV_GRAPH::Dij(n);
int ans=0;
for(int re i=0;i<=k;++i){
ans=(ans+dfs(1,i))%mod;
if(!flag)break;
}
printf("%d\n",flag?ans:-1);
}
return 0;
}