所谓k短路,就是第k短的路。
(逃)
解析
给出一个有向图,求 s−ts-ts−t 的不严格第 k 短的路径。
A*算法
对于一个状态 (x,cost)(x,cost)(x,cost),即到 xxx 时走过长度为 costcostcost,定义一个估价函数:
f=cost+dis(x,t)f=cost+dis(x,t)f=cost+dis(x,t)
以这个为关键字维护优先队列,当 ttt 被访问到第 kkk 次时的估价函数即答案。
最差时间复杂度可以卡到 O(nklog(n))O(nk\log (n))O(nklog(n))。
可持久化可并堆
先在反图任意找到一棵最短路径树。
任意一条路径都由若干条树边和非树边组成,每条非树边导致的额外代价是 disv−disu+wdis_v-dis_u+wdisv−disu+w。
对于相邻两条非树边 x,yx,yx,y,yyy 的起点必然是 xxx 的终点的祖先或本身。
对于任意一个符合该性质的合法非树边集合,都能双射到一条合法路径上,所以问题就转化成了找到权值第 kkk 小的集合。
还是维护一个优先队列,记录最后一条边的终点和集合总权值。每次弹出队首时,能出现两种新的状态:
- 最后一条边被替代成合法且权值比它大的权值最小的边。
- 在祖先新增一条权值最小的合法边。
可以对于每个节点维护一个堆,存储起点在自己及其祖先的所以非树边,即可实现2。
对于1,我们直接把其对应的堆节点的左右儿子加入即可。
时间复杂度 O((n+m)logm+klogk)O((n+m)\log m+k\log k)O((n+m)logm+klogk)