题目来源于《算法导论》第15章动态规划的习题 15-1,显然建议使用DP
对最小距离大家应该都比较熟悉,比如对非负权值图中有Dijkstra算法,对负权值图中有Ford算法。 最远距离?假设从A到F的最远距离为A->C->D->E->F, 为什么D->E->F一定会是从D到F的最远距离?我在这点证明困扰了很久,直到最近才想明白其中原理。
当重新审视有向(directed) 无回路(acyclic)这两个词时,我才突然想到原来可以这样证明:
依然假设A到F的最远距离为A->C->D->E->F, 现在考虑从D到F:如果存在B,使得D->B->F更远,那么我们直接可以用这段路径代替D->E->F, 这与我们之前的假设相矛盾;如果D经过C再到达F的距离更远,比如D->C->(E)->F, 那就说明存在回路D<->C, 这与条件相矛盾。所以,这里,D->E->F必然是从D到F的最远路径。算法的理论基础终于找到了!
OK,既然最远子路径是问题的必要条件,那么反过来,我们找到每一个点(除了终点以外)到达终点的最远路径,就可以作为整个问题的充分条件。我们需要一个合适的顺序,遍历所有顶点,从终点开始,逐渐向外扩展。问题到了这里就很明显了,采用拓扑序,广度优先的方式遍历。
具体实现中,我用了一个queue存放BFS中覆盖到的顶点。注意在每加入一个新的顶点v时,除了要遍历已计算过的顶点再确定最大的path[v]时,还要反过来考虑对于已经计算过最远距离的顶点u,如果存在权边u->v,那么path[u]也可能需要更新,这一步是最