题目描述
策策同学特别喜欢逛公园。公园可以看成一张NN个点MM条边构成的有向图,且没有 自环和重边。其中1号点是公园的入口,NN号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。
策策每天都会去逛公园,他总是从1号点进去,从NN号点出来。
策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到NN号点的最短路长为dd,那么策策只会喜欢长度不超过d + Kd+K的路线。
策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?
为避免输出过大,答案对PP取模。
如果有无穷多条合法的路线,请输出-1−1。
输入输出格式
输入格式:
第一行包含一个整数 TT, 代表数据组数。
接下来TT组数据,对于每组数据: 第一行包含四个整数 N,M,K,PN,M,K,P,每两个整数之间用一个空格隔开。
接下来MM行,每行三个整数a_i,b_i,c_iai,bi,ci,代表编号为a_i,b_iai,bi的点之间有一条权值为 c_ici的有向边,每两个整数之间用一个空格隔开。
输出格式:
输出文件包含 TT 行,每行一个整数代表答案。
输入输出样例
输入样例#1: 复制
2
5 7 2 10
1 2 1
2 4 0
4 5 2
2 3 2
3 4 1
3 5 2
1 5 3
2 2 0 10
1 2 0
2 1 0
输出样例#1: 复制
3
-1
吸氧才能过==
非常分层图啊有没有
冷静分析发现我们的分层图其实是个DAG!!!
若果不是DAG那就是有0环,而且环不会跨层
对于每一层记搜,如果到了访问道过的边就是有0环
可以建反图跑最路减枝
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊不开O2我!也!!过!!了!!!!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define M 200010
#define RI register int
using namespace std;
priority_queue <pair<int,int> >q;
int i,m,n,h,j,k,t,ver[M],nex[M],head[M],cnt,edge[M],x,y,z,s[M],f[M][55],p,d,r[M],ver1[M],nex1[M],head1[M];
int bl[M],b[55][M];
inline char gc()
{
static char now[1<<22],*S,*T;
if (T==S)
{
T=(S=now)+fread(now,1,1<<22,stdin);
if (T==S) return EOF;
}
return *S++;
}
inline int gtt()
{
register int x=0,f=1;
register char ch=gc();
while(!isdigit(ch))
{
if (ch=='-') f=-1;
ch=gc();
}
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=gc();
return x*f;
}
inline void add(int x,int y,int z)
{
cnt+=1;
ver[cnt]=y; nex[cnt]=head[x]; head[x]=cnt; edge[cnt]=z;
ver1[cnt]=x; nex1[cnt]=head1[y]; head1[y]=cnt;
}
inline void dji(int fr,int *w,int e)
{
w[fr]=0;
while(q.size()) q.pop();
q.push(make_pair(0,fr));
while(q.size())
{
while(q.size() &&(bl[q.top().second])) q.pop();
if(!q.size()) break;
int x=q.top().second; q.pop(); bl[x]=1;
for(RI i=head[x];i;i=nex[i])
{
RI t=ver[i];
if(w[x]+edge[i]<w[t])
{
w[t]=w[x]+edge[i];
q.push(make_pair(-w[t],t));
}
}
}
}
inline void dji1(int fr,int *w,int e)
{
w[fr]=0;
while(q.size()) q.pop();
q.push(make_pair(0,fr));
while(q.size())
{
while(q.size() &&(bl[q.top().second])) q.pop();
if(!q.size()) break;
int x=q.top().second; q.pop(); bl[x]=1;
for(RI i=head1[x];i;i=nex1[i])
{
RI t=ver1[i];
if(w[x]+edge[i]<w[t])
{
w[t]=w[x]+edge[i];
q.push(make_pair(-w[t],t));
}
}
}
}
int dfs(int now,int x,int z)
{
b[now][x]=1;
if(bl[x]) return 0;
bl[x]=1;
for(RI i=head[x];i;i=nex[i])
{
int t=ver[i], y=1;
if(r[t]+s[t]+now>s[n]+k) continue;
if(s[x]+edge[i]==s[t])
{
f[t][now]=z+f[t][now];
if(f[t][now]>p) f[t][now]-=p;
if(b[now][t]) y=dfs(now,t,z);
else y=dfs(now,t,f[t][now]);
if(!y) return 0;
}
else if(now+s[x]+edge[i]-s[t]<=k) {
f[t][now+s[x]+edge[i]-s[t]]+=z;
if(f[t][now+s[x]+edge[i]-s[t]]>p) f[t][now+s[x]+edge[i]-s[t]]-=p;
}
}
bl[x]=0;
return 1;
}
int main()
{
t=gtt();
for(t;t;t--)
{
memset(nex,0,sizeof(nex));
memset(head,0,sizeof(head));
memset(nex1,0,sizeof(nex));
memset(head1,0,sizeof(head));
memset(f,0,sizeof(f));
n=gtt(); m=gtt(); k=gtt(); p=gtt(); cnt=0;
for(RI i=1;i<=m;i++)
{
x=gtt(); y=gtt(); z=gtt();
add(x,y,z);
}
memset(s,0x3f,sizeof(s));
memset(r,0x3f,sizeof(r));
memset(b,0,sizeof(b));
memset(bl,0,sizeof(bl)); dji1(n,r,0);
memset(bl,0,sizeof(bl)); dji(1,s,1);
memset(bl,0,sizeof(bl));
f[1][0]=y=1;
for(i=0;i<=k;++i)
{
for(j=1;j<=n;++j)
{
if(s[j]+i+r[j]<=k+s[n] && !b[i][j] && f[j][i] && s[j]<0x3f3f3f3f) y=dfs(i,j,f[j][i]);
if(!y){printf("-1
"); break;}
}
if(!y) break;
}
if(!y)continue;
int ans=0;
for(RI i=0;i<=k;++i)
{
ans=ans+f[n][i];
if(ans>p) ans-=p;
}
printf("%d
",ans);
}
}