题解 P3953 【逛公园】

· · 题解

题意:求dis(1,n)<=MinDis(1,n)+K的路径数

算法一:

首先你可以考虑到Day1DP去哪里了?

没错,你只要再注意一下K\le50就大概能想到这是一个与k有关的DP

①:考虑30pts:K=0

右转P1608路径统计(P1144最短路计数可以顺带A掉)

②:考虑70pts:没有0

dis1_u表示1到u的最短路,disn_u表示un的最短路(这个可以建反图跑出来)

考虑f[u][j]表示dis(1,u)\le dis1_u+j的路径数

那么对于edge(u,v,w)

那么从1->u->v这条路径的长度就是dis1_u+j+w-dis1_v

如果dis1_u+w-dis1_v+j\le K

就可以从f[u][j]转移到f[v][dis1_u+j+w-dis1_v]

所以直接先从1跑最短路然后直接O(KM)DPok

当然这样还是有问题的

因为我们必须要先更新dis1小的点

所以要先按照dis1排个序再去转移就有70pts

③:考虑100pts:

对于有0边的图,显然直接按照dis1去排序是不行的

例如a->b->c,w=0

因为他的一个有向图,更新顺序显然是a,b,c

所以考虑拓扑排序来确定0边两个端点的更新顺序

即对于0边,把其加入新图,然后对于新图拓扑排序确定"0点"的更新顺序

然后对于-1的情况显然是对于一条满足条件的路径上有一个0

拓扑排序完了且入度不等于0说明这个点在0环上

同一个0环上任意一个点到1的最短路和到n的最短路都一样

所以当这个点i满足dis1_i+disn_i<=dis1_n+K时,就可以输出-1

然后最后以dis1disn为第一关键字,拓扑序为第二关键字排序再转移就ok

算法二:

只要跑一次反向的最短路

f[u][k]$表示$dis(u,n)<=MinDis(u,n)+k$的方案数,答案就是$f[1][K]

考虑egde(u,v,w)

同样的道理走这条边的话,dis(v,n)=MinDis(v,n)+w-MinDis(u,n)

\Rightarrow f[u][k]=∑f[v][k-(MinDis(v,n)-MinDis(u,n)+w)]

这样怎么判0环呢?只要在搜索的时候记录个instackok

如果当前的v还在搜索的栈中就可以直接返回-1