用DP来解决,在只使用顶点0~k和i,j的情况下(i,j作为起点和重点,0~k个点作为中间点),记i到j的最短长度为dp[k][i][j],k=-1表示只是用i和j两个点,此时dp[0][i][j]=cost[i][j]
接下来,我们分i到j的最短路恰好经过k和不经过k两种,如果不经过k点
那么就是dp[k-1][i][j],如果经过k点,就是dp[k-1][i][k]+dp[k-1][k][j]
所以dp[k][i][j]=MIN{dp[k-1][i][j] , dp[k-1][i][k]+dp[k-1][k][j]}
这个dp可以使用同一个数组,前面的k只要放在外层循环就行了。
所以
<pre name="code" class="cpp">for i=0->V
for j=0->V
for l=0->V;
dp[i][j]=min{dp[i][j],dp[i][k]+dp[k][j]}
可以求出负环,只要某个顶点dis[i][j]为负说明有负环。
注意这个循环一定要k在外层,因为k说明了中间点的个数,中间点一定要从少到多推过去
对于路径还原,由于Dijkstrea,spfa,Floyd算法都是一种动态接近的思想,所以在每次状态转移的时候进行记录就可以了,维护一个pre数组就可以完成这个工作