[NOIP] [最短路] [拓扑排序] [DP] NOIP2017Day1 逛公园

题目传送门
考试 T3 看到策策就已经鏼鏼发抖了……然而 T2 几乎敲了2h,就没时间了,敲个暴力 10 10 10 分走人……
注意到 k ≤ 50 k\le 50 k50 ,考虑 DP……
dp [ u ] [ len ] \text{dp}[u][\text{len}] dp[u][len] 表示走过路径比 1 → u 1\to u 1u 的最短路多 len \text{len} len 长度的路径条数。
v v v u u u 的后继节点, u → v u\to v uv 的权值为 w w w,转移是这样的:
dp [ v ] [ dis u + len + w − d i s v ] = d p [ v ] [ dis u + len + w − d i s v ] + dp [ u ] [ len ] \text{dp}[v][\text{dis}_u+\text{len}+w-dis_v]={dp}[v][\text{dis}_u+\text{len}+w-dis_v]+\text{dp}[u][\text{len}] dp[v][disu+len+wdisv]=dp[v][disu+len+wdisv]+dp[u][len]
其中, dis i \text{dis}_i disi 表示 1 → i 1\to i 1i 的最短路径长度。
初值为: dp [ 1 ] [ 0 ] = 1 \text{dp}[1][0]=1 dp[1][0]=1
这样我们会发现这个 DP 转移是存在环的,在最短路上的点和零环上的点都可以在同一层互相转移……
于是我们对最短路径上的边以及零边拿来做拓扑排序,这样更新就有顺序了,在最短路上的边和零边就严格按照拓扑序进行转移。
注意到如果有一个零环位于 1 → n 1\to n 1n 的长度为 dis n + k \text{dis}_n+k disn+k 的路径上,则路径条数无穷多(绕零环跑无穷圈),输出 − 1 -1 1
不过,跑 DFS 进行记忆化搜索可能更快一些……
Code

你可能感兴趣的:(最短路,DP,NOIP)