题目描述
策策同学特别喜欢逛公园。公园可以看成一张N个点M条边构成的有向图,且没有自环和重边。其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的时间。
策策每天都会去逛公园,他总是从1号点进去,从N号点出来。
策策喜欢新鲜的事物,他不希望有两天逛公园的路线完全一样,同时策策还是一个特别热爱学习的好孩子,他不希望每天在逛公园这件事上花费太多的时间。如果1号点到N号点的最短路长为e,那么策策只会喜欢长度不超过e+K的路线。
策策同学想知道总共有多少条满足条件的路线,你能帮帮他吗?
为避免输出过大,答案对P取模。
如果有无穷多条合法的路线,请输出−1。
题目分析
本人一开始还以为是什么高级题目。
我们设
f[i][j]
为第i个点,超出这个点到1号点最短距离的j个单位长度的方案数
然后从第n个点开始记忆化搜索即可
代码
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
int x,y,c,next;
}a[210000];int len,last[110000];
int n,m,k,p;
void ins(int x,int y,int c)
{
len++;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
}
int st,ed;
int d[110000];
int list[110000],head,tail;
bool v[110000];
void spfa()
{
for(int i=1;i<=n;i++)
{
d[i]=999999999;
}
d[st]=0;
memset(v,true,sizeof(v));
v[st]=false;
list[1]=st;head=1;tail=2;
if(tail==n+1) tail=1;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(d[y]>d[x]+a[k].c)
{
d[y]=d[x]+a[k].c;
if(v[y]==true)
{
list[tail]=y;v[y]=false;
tail++;if(tail==n+1) tail=1;
}
}
}
v[x]=true;
head++;
if(head==n+1) head=1;
}
}
int f[110000][61];bool bk[110000][61],bz;
void dfs(int x,int c)
{
if(bk[x][c]==false)
{
bz=false;
return ;
}
bk[x][c]=false;
if(x==1&&c==0)
{
f[1][0]=0;
}
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
int temp=(c+d[x]-d[y])-a[k].c;
if(temp>=0)
{
if(f[y][temp]==-1)
{
dfs(y,temp);
if(bz==false) return ;
}
f[x][c]=(f[x][c]+f[y][temp])%p;
}
}
f[x][c]=(f[x][c]+1)%p;
bk[x][c]=true;
}
int x1[210000],y1[210000],c1[210000];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
len=0;memset(last,0,sizeof(last));
scanf("%d%d%d%d",&n,&m,&k,&p);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x1[i],&y1[i],&c1[i]);
ins(x1[i],y1[i],c1[i]);
}
st=1;ed=n;
spfa();
for(int i=1;i<=n;i++)
{
for(int j=0;j<=k;j++)
{
f[i][j]=-1;
}
}
len=0;memset(last,0,sizeof(last));
for(int i=1;i<=m;i++)
{
ins(y1[i],x1[i],c1[i]);
}
memset(bk,true,sizeof(bk));
bz=true;int ans=0;
for(int i=0;i<=k;i++)
{
dfs(n,i);ans=(ans+f[n][i])%p;
if(bz==false) break;
}
if(bz==false) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}