[NOIP2017]逛公园

题意

d i s ( 1 , n ) < = M i n D i s ( 1 , n ) + K dis(1,n)<=MinDis(1,n)+K dis(1,n)<=MinDis(1,n)+K的路径数


题解

算法一:

首先你可以考虑到 D a y 1 Day1 Day1 D P DP DP去哪里了?

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

①:考虑$30pts:K=0 $

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

②:考虑 70 p t s 70pts 70pts:没有 0 0 0

d i s 1 u dis1_u dis1u表示1到u的最短路, d i s n u disn_u disnu表示 u u u n n n的最短路(这个可以建反图跑出来)

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

那么对于 e d g e ( u , v , w ) edge(u,v,w) edge(u,v,w)

那么从 1 − > u − > v 1->u->v 1>u>v这条路径的长度就是 d i s 1 u + j + w − d i s 1 v dis1_u+j+w-dis1_v dis1u+j+wdis1v

如果 d i s 1 u + w − d i s 1 v + j ≤ K dis1_u+w-dis1_v+j\le K dis1u+wdis1v+jK

就可以从 f [ u ] [ j ] f[u][j] f[u][j]转移到 f [ v ] [ d i s 1 u + j + w − d i s 1 v ] f[v][dis1_u+j+w-dis1_v] f[v][dis1u+j+wdis1v]

所以直接先从 1 1 1跑最短路然后直接 O ( K M ) D P O(KM)DP O(KM)DP o k ok ok

当然这样还是有问题的

因为我们必须要先更新 d i s 1 dis1 dis1小的点

所以要先按照 d i s 1 dis1 dis1排个序再去转移就有 70 p t s 70pts 70pts

③:考虑 100 p t s : 100pts: 100pts:

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

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

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

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

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

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

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

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

所以当这个点 i i i满足 d i s 1 i + d i s n i < = d i s 1 n + K dis1_i+disn_i<=dis1_n+K dis1i+disni<=dis1n+K时,就可以输出 − 1 -1 1

然后最后以 d i s 1 dis1 dis1 d i s n disn disn为第一关键字,拓扑序为第二关键字排序再转移就 o k ok ok

算法二:

只要跑一次反向的最短路

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

考虑 e g d e ( u , v , w ) egde(u,v,w) egde(u,v,w)

同样的道理走这条边的话, d i s ( v , n ) = M i n D i s ( v , n ) + w − M i n D i s ( u , n ) dis(v,n)=MinDis(v,n)+w-MinDis(u,n) dis(v,n)=MinDis(v,n)+wMinDis(u,n)

⇒ f [ u ] [ k ] = ∑ f [ v ] [ k − ( M i n D i s ( v , n ) − M i n D i s ( u , n ) + w ) ] \Rightarrow f[u][k]=∑f[v][k-(MinDis(v,n)-MinDis(u,n)+w)] f[u][k]=f[v][k(MinDis(v,n)MinDis(u,n)+w)]

这样怎么判 0 0 0环呢?只要在搜索的时候记录个 i n s t a c k instack instack o k ok ok

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值