P3953 [NOIP2017 提高组] 逛公园
总算把咕了快四年的题A了QAQ。
题意
给出 N,M,K,P,一个包含 N 个点 M 条边的有向图,没有自环和重边,顶点编号从 1∼N。
令 dis(u,v) 为从 u 出发到达 v 的最短路径,求从顶点 1 到顶点 N 的路程小于等于 dis(1,N)+K 的路径数目。
答案对 P 取模。
思路
计数问题又可以考虑dp了,先用dijkstra算法求出顶点 1 到每个顶点的最短距离。
设 f(u,j) 表示,从顶点 1 到顶点 u 距离满足小于等于 dis(1,u)+j 的路径数目,j 也就是当前距离和最短距离在容许范围内的最大差值。
考虑一条有向边 (u,v),边权为 wu,v,则转移为:
f(v,dis(1,u)+j+wu,v−dis(1,v))+=f(u,j)
其中 dis(1,u)+j+wu,v−dis(1,v) 表示在 dis(1,u)+j 的基础上加上权值 wu,v 后获得的总距离,再和最短距离 dis(1,v) 做差获得差值,当差值非负的时候就能进行转移。
由于上式不好直接正推出来,所以考虑记忆化搜索实现dp的转移,于是将上式改写成:
f(u,j)+=f(v,j+dis(1,u)−dis(1,v)−wv,u)
于是先反向建图,然后在反向图中进行记忆化搜索即可。
关于零环的判断,只要在记忆化搜索中,判断 f(u,j) 有没有在同一次搜索中出现两次即可,因为如果出现两次,当且仅当通过路程上的点的最短距离都相等,且边权值都为0,这就一定是0环了。
而且这样不会被卡数据,因为这不是直接去找0环,而是在满足 j⩾0 的前提下去找的,这样就保证了这个0环一定是可以到达的。
解释一下可以到达的含义:如果 K 特别小,比如是 K=0,如果在1到N的最短路外出现了一个零环,对答案是没有任何影响的,因为你根本走不到这个位置。
注: 构造了一个特殊原点编号为0,它向顶点1连接一条边权为0的有向边,这样在记忆化搜索中,就不会找到 f(1,0) 就提前返回了,而没有判断顶点1是否是在0环中。
初始化:f(0,0)=0。
点击显/隐代码