题目大意:求出图中最短路的条数+比最短路长度大1的路条数。
好题,需要比较深刻地理解Dijkstra的思想。
如果直接求比最短路大1的路,不太好把它转化成一个阶段性、符合最优子结构的模型,求解起来可能会比较麻烦。
所以我们直接求次短路的条数,然后判断下次短路是不是比最短路大1即可。
二维Dijkstra求次短路(k很小时的k短路也适用):
我们知道Dijkstra就是不断地用已经确定最短路的节点(黑色)去松弛未确定的点(白色),用数学归纳法很容易证明这是正确的。它的
核心思想就是
某个节点的最短路一定是由它前驱节点的最短路扩展来的。那么对于次短路也可以类似的看:一个节点的次短路一定是由它前驱节点的最短路 or 次短路扩展而来的。那么我们就可以把节点分成两层处理:一层处理、存储最短路,另一层处理、存储次短路。这样, 用于记录状态的数组变成了二维, 放进堆中的状态也必须是"二维"的, 这里的"二维"并不是要你开个二维数组, 而是需要在放入堆中的结构体里多加一个标记变量, 用于标识到底是最短路还是次短路, 当然, 用于标记已经确定最短路、次短路的点的closed表同样要变成二维的。循环结束条件是堆为空, 因为要计数, 就必须遍历所有情况.
具体在做状态转移的时候, 拿到当前状态, 扩展下一状态, 设当前状态长度为d, 下一状态最短路和次短路状态分别是d0和d1, 则:
d小于d0, 则d1=d0,d0=d, 计数都重置为所赋的值对应的计数.
d等于d0, 则累加最短路计数.
d小于d1, 则d1=d, 重置次短路计数为所赋的值对应的计数.
d等于d1, 则累加次短路计数.
#include
#include
#include
#include
#include
#include
#include
#include
#include