P3953 [NOIP2017 提高组] 逛公园


#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#define re register int
#define fo(i,a,b) for (re i=a;i<=b;i++)
using namespace std;

const int inf=0x3f;
const int maxn=200000+50;
const int mxn=100000+50;
int T,n,m,k,p,sum1,sum2;
int head[mxn],rev[mxn],dist[mxn],vis[mxn],wd[mxn][50+15],f[mxn][50+15];
//设f[u][know]为到u点时与从终点开始的最短路的偏移量为know的时候的总方案数目。
bool flag;
struct EDGE
{
	int to,next,val;
}edge[maxn],reve[maxn];
inline int read() {
    char ch = getchar();int ret=0;
    while(ch<'0'||ch >'9') ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return ret;
}
void init()
{
	memset(head,-1,sizeof(head));
	memset(rev,-1,sizeof(rev));
	sum1=0;sum2=0;
	memset(edge,0,sizeof(edge));
	memset(reve,0,sizeof(reve));
	memset(f,-1,sizeof(f));
	flag=false;
}
void add(int x,int y,int z)
{
	edge[++sum1]=(EDGE){y,head[x],z};
	head[x]=sum1;
}
void addr(int x,int y,int z)
{
	reve[++sum2]=(EDGE){y,rev[x],z};
	rev[x]=sum2;
}
void spfa()
{
	queue <int> q;
	memset(dist,inf,sizeof(dist));
	memset(vis,0,sizeof(vis));
	dist[n]=0;
	vis[n]=1;
	q.push(n);
	while (!q.empty())
	{
		int x=q.front();q.pop();vis[x]=0;
		for (int i=rev[x];i!=-1;i=reve[i].next)
		if (dist[reve[i].to]>dist[x]+reve[i].val){
			dist[reve[i].to]=dist[x]+reve[i].val;
			if (!vis[reve[i].to])
			{
			  vis[reve[i].to]=1;
			  q.push(reve[i].to);	
			}
		}	
	}
}
int dfs(int u,int know)
{
	if (wd[u][know]) {flag=true;return 0;}
	if (f[u][know]>0) return f[u][know];
	wd[u][know]=1;
	int sum=0;
	for (int i=head[u];i!=-1;i=edge[i].next)
	{
		int tmp=know-(dist[edge[i].to]+edge[i].val-dist[u]);
		if (tmp<0||tmp>k) continue;
		sum=(sum+dfs(edge[i].to,tmp))%p;
		if (flag) return 0;
	}
	if (u==n&&know==0) sum=1;
	wd[u][know]=0;
	return f[u][know]=sum;
}
int main()
{
	T=read();
	while (T--)
	{
	init();	
	scanf("%d%d%d%d",&n,&m,&k,&p);
	fo(i,1,m) 
	{
		int x=read(),y=read(),z=read();
		add(x,y,z);
		addr(y,x,z);
	 }
	spfa();
	int ans=0; 
	fo(i,0,k) 
	{
	memset(wd,0,sizeof(wd));
	ans=(ans+dfs(1,i))%p;
}
	if (flag) puts("-1");else printf("%d\n",ans);
	}
	return 0;
}
posted @ 2022-05-07 16:27  wzx_believer  阅读(43)  评论(0)    收藏  举报