记录编号 578494 评测结果 AAAAAAAAAA
题目名称 [NOIP 2017]逛公园 最终得分 100
用户昵称 Gravataryrtiop 是否通过 通过
代码语言 C++ 运行时间 2.626 s
提交时间 2023-03-22 07:55:49 内存使用 65.52 MiB
显示代码纯文本
#include <bits/stdc++.h>
#define pb emplace_back
#define fir first
#define sec second
#define Chtholly std::set<node>::iterator
using i64 = long long;
using u64 = unsigned long long;
using pii = std::pair<int,int>;
using pli = std::pair<i64,int>;

const int maxn = 1e5 + 5;
const int maxm = 55;
int n,m,k;
i64 mod;
void add(i64& x,i64 y) {x += y;if(x >= mod)x -= mod;return ;}
void sub(i64& x,i64 y) {x -= y;if(x < 0)x += mod;return ;}
i64 inc(i64 x,i64 y) {return (x + y) >= mod ? (x + y - mod) : (x + y);}
i64 dec(i64 x,i64 y) {return (x - y) < 0 ? (x - y + mod) : (x - y);}
i64 power(i64 x,i64 y) {i64 ans = 1;for(;y;y >>= 1) {if(y & 1)(ans *= x) %= mod;(x *= x) %= mod;}return ans;}
std::vector<pii> G[maxn],S[maxn];
std::vector<int> Z[maxn],scc[maxn];
i64 dis[maxn],dist[maxn];
bool vis[maxn],ins[maxn],tra[maxn][maxm];
int stk[maxn],tp,dfn[maxn],low[maxn],tot,num,bel[maxn];

void tarjan(int u) {
	stk[++ tp] = u;
	ins[u] = true;
	dfn[u] = low[u] = ++ num;
	for(auto& v : Z[u]) {
		if(!dfn[v])
			tarjan(v),low[u] = std::min(low[u] , low[v]);
		else if(ins[v])
			low[u] = std::min(low[u] , dfn[v]);
	}
	if(dfn[u] == low[u]) {
		++ tot;
		do {
			scc[tot].pb(u);
			bel[u] = tot;
			ins[u] = false;
		} while(stk[tp --] != u);
	}
	return ;
}

i64 f[maxn][maxm];

i64 dp(int x,int y) {
	if(x == 1&&y == 0)
		return 1;
	if(tra[x][y])
		return f[x][y];
	tra[x][y] = true;
	i64& val = f[x][y];
	for(pii& p : S[x]) {
		int v = p.fir,w = p.sec;
		if(dis[x] - dis[v] + y - w >= 0&&dis[x] - dis[v] + y - w <= k)
			add(val , dp(v , dis[x] - dis[v] + y - w));
	}
	return val;
}

void work() {
	scanf("%d %d %d %lld",&n,&m,&k,&mod);
	for(int i = 1;i <= tot;++ i)
		scc[i].clear();
	tot = tp = num = 0;
	for(int i = 1;i <= n;++ i)
		G[i].clear(),S[i].clear(),Z[i].clear();
	memset(dfn , 0 , sizeof(dfn));
	memset(low , 0 , sizeof(low));
	memset(bel , 0 , sizeof(bel));
	for(int i = 1;i <= m;++ i) {
		int u,v,t;
		scanf("%d %d %d",&u,&v,&t);
		G[u].pb(v , t);
		S[v].pb(u , t);
		if(!t)
			Z[u].pb(v);
	}
	memset(vis , false , sizeof(vis));
	memset(dis , 0x3f , sizeof(dis));
	std::priority_queue<pli,std::vector<pli>,std::greater<pli> > q;
	q.emplace(dis[1] = 0 , 1);
	while(!q.empty()) {
		int u = q.top().sec;
		q.pop();
		if(vis[u])
			continue ;
		vis[u] = true;
		for(pii& p : G[u]) {
			int v = p.fir,w = p.sec;
			if(dis[v] > dis[u] + w)
				q.emplace(dis[v] = dis[u] + w , v);
		}
	}
	memset(vis , false , sizeof(vis));
	memset(dist , 0x3f , sizeof(dist));
	q.emplace(dist[n] = 0 , n);
	while(!q.empty()) {
		int u = q.top().sec; 
		q.pop();
		if(vis[u])
			continue ;
		vis[u] = true;
		for(pii& p : S[u]) {
			int v = p.fir,w = p.sec;
			if(dist[v] > dist[u] + w)
				q.emplace(dist[v] = dist[u] + w , v);
		}
	}
	for(int i = 1;i <= n;++ i)
		if(!dfn[i])
			tarjan(i);
	for(int i = 1;i <= tot;++ i) {
		if(scc[i].size() <= 1)
			continue ;
		for(auto& v : scc[i])
			if(dis[v] + dist[v] <= dis[n] + k)
				return puts("-1"),void();
	}
	memset(f , 0 , sizeof(f));
	memset(tra , false , sizeof(tra));
	i64 ans = 0;
	for(int i = 0;i <= k;++ i)
		add(ans , dp(n , i));
	printf("%lld\n",ans);
	return ;
}

int main() {
	freopen("2017park.in","r",stdin);
	freopen("2017park.out","w",stdout);
	int T;
	scanf("%d",&T);
	while(T --)
		work();
	return 0;
}