[题解]P3953 [NOIP 2017 提高组] 逛公园

P3953 [NOIP 2017 提高组] 逛公园

给定边权非负的有向图,记其最短路为 \(d\),求长度不超过 \(d+k\) 的路径总数,或报告有无穷多条。
\(n\le 10^5,m\le 2\times 10^5,k\le 50\)

考虑到 \(k\) 很小,我们令 \(f[u][i]\)\(1\to u\),比最短路 \(d[u]\) 多走了 \(k\) 的长度的方案数。

则有转移:

\[f[u][i]=\sum\limits_{(v,u)\in E} f[v][x] \]

其中 \(d_u+i=d_v+x+w(u,v)\),即 \(x=d_u+i-d_v-w(u,v)\)

若符合条件的路径上没有零权环,这样子是没有后效性的。

反之,若有零权环,则说明有无穷多条路径。可以在转移 \(f\) 的过程中完成判定。

总时间 \(O(m\log m+n)\)。瓶颈在于 Dijkstra。

点击查看代码
#include<bits/stdc++.h>
#define eb emplace_back
#define PII pair<int,int>
#define int long long
using namespace std;
const int N=1e5+5,K=52;
int t,n,m,k,P,f[N][K],d[N];
struct Ed{int to,w;};
bool flg;
vector<Ed> G[N],G2[N];
bitset<N> vis;
bitset<K> in[N];
priority_queue<PII,vector<PII>,greater<PII>> q;
inline void dij(int s){
	memset(d,0x3f,sizeof d);
	d[s]=0,q.push({0,s});
	while(!q.empty()){
		int u=q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(Ed i:G[u]){
			int v=i.to,w=i.w;
			if(d[u]+w<d[v]){
				d[v]=d[u]+w;
				q.push({d[v],v});
			}
		}
	}
}
inline int dfs(int u,int dd){//dd: 到u的路径长度
	int ex=dd-d[u],s=0;//额外走了多少
	if(ex<0||ex>k) return 0;
	if(in[u][ex]) return flg=1,0;
	if(~f[u][ex]) return f[u][ex];
	in[u][ex]=1;
	for(Ed i:G2[u]){
		int v=i.to,w=i.w,x=dfs(v,dd-w);
		if(flg) return in[u][ex]=0;
		(s+=x)%=P;
	}
	in[u][ex]=0;
	if(u==1&&!ex) s=1;//为了找环 需要在这里赋初值
	return f[u][ex]=s;
}
inline void clr(){
	vis=flg=0;
	for(int i=1;i<=n;i++) G[i].clear(),G2[i].clear();
	memset(f,-1,sizeof f);
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>t;
	while(t--){
		cin>>n>>m>>k>>P;
		clr();
		for(int i=1,u,v,w;i<=m;i++){
			cin>>u>>v>>w;
			G[u].eb(Ed{v,w});
			G2[v].eb(Ed{u,w});
		}
		dij(1);
		int ans=0;
		for(int i=0;i<=k;i++) (ans+=dfs(n,d[n]+i))%=P;
		if(flg) cout<<"-1\n";
		else cout<<ans<<"\n";
	}
	return 0;
}
posted @ 2025-11-26 14:01  Sinktank  阅读(130)  评论(0)    收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.