题意不说了,有特殊要求的最短路。对于单源最短路,我是无脑上SPFA,SPFA也写了不下十遍,然而这次没有处理好。关于SPFA,多说几句,个人感觉就是优化的BFS,优化在哪了呢?就是对入队的节点有标准,只有对当前状态可能有帮助的节点才会入队,有一种“松弛”的感觉,而且个人感觉这其实是建一棵树的过程。
然而这次在25分卡了好久,最后总算想到了自己哪里没考虑周全,这里是AC代码。题中说如果最短路不止一条,取换乘最少的,此结果唯一。我的做法是dis数组保存距离,cnt数组保存换乘次数,preS保存前驱车站,preL保存前驱线路id。对于队首的节点,对其相连的点做松弛操作,而这里就是关键。距离变短了,肯定要松弛(修改前驱)并入队;距离不变,但换乘变少,肯定也要修改。那距离和换乘都不变的话,要不要入队呢?
答案是肯定的。又回到了本题给出的前提,所谓的结果唯一,但是中间结果不一定唯一(联想到最优子结构)。而我最开始却没有入队,也就是代码第54行,最初写的是“<”号而不是“<=”,如下,具体的反例注释在了代码最后。其实还有个问题,这样会不会无限循环(不停入队出队)?其实是不会的,这个问题留给读者思考。
if (tmp <=cnt[v])
{
……
}
网上大佬们貌似都是清一色的dfs,把整个路径都存下来,然后判断、取舍、输出,所有的路径都会走到,因而不会出现我这样的问题。其实只有这类“答案不唯一,但是XXX这样的答案保证唯一”这种情况下才容易发生我这样的错误。所以教训就是:要么考虑周全,想清楚最优子结构是否唯一,不唯一怎么办;要么就采用稳妥的方法,多写几行代码,比如记录下所有的路径,之后再作判断。