最长路径问题
- 在一般的图中,最长路径问题不具有如最短问题一样的最优子结构属性(算法导论动态规划章节P218)
- 在最长路径问题中,子问题是相关的
- 在最短路径问题中,子问题是无关的
- 因此存在动态规划算法!
- flody和Dijkstra都可以认为是动态规划算法
- NP−hardNP-hardNP−hard问题
- 但是,对于directed acyclic graphdirected \ acyclic \ graphdirected acyclic graph来说,存在线性时间算法,即拓扑排序!
有向无环图中的最长路径问题-拓扑排序(类似关键路径问题)
算法流程
- 使用BFS对所有结点进行拓扑排序
- 在拓扑排序过程中每当遇到一个结点(设为结点j),更新从其出发的所有结点的dist值。对于从结点i出发的任意一条边(i,j)按如下方式进行更新:
dist[j]←max{dist[j],dist[i]+weight(i,j)}dist[j] \leftarrow max\{dist[j],dist[i] + weight(i,j)\}dist[j]←max{dist[j],dist[i]+weight(i,j)} - 最终取dist的最大值即可
例:leetcode-Longest Increasing Path in a Matrix

记忆化搜索
class Solution {
public int DFS(int i,int j,int[][] longest,int[][] matrix,int[][] choice,int cur)
{
if(longest[i][j]!=0)
{
return longest[i][j];
}
longest[i][j] = 1;
for(int[] c : choice)
{
if(i + c[0]>=0 && i+c[0]<matrix.length && j + c[1]>=0 && j+c[1]<matrix[0].length && matrix[i + c[0]][j + c[1]] > matrix[i][j])
longest[i][j] = Math.max(longest[i][j],1 + DFS(i + c[0],j + c[1],longest,matrix,choice,cur));
}
return longest[i][j];
}
public int longestIncreasingPath(int[][] matrix) {
int ans = -1;
int[][] longest = new int[matrix.length][matrix[0].length];
int[][] choice = new int[][]{{-1,0},{1,0},{0,1},{0,-1}};
for(int i = 0;i<matrix.length;i++)
for(int j = 0;j<matrix[0].length;j++)
{
ans = Math.max(ans,DFS(i,j,longest,matrix,choice,1));
}
return ans;
}
}
有向无环图中的最长路径
- 对于矩阵中的每个格子将其看作一个结点
- 对于结点检查其相邻结点(即上下左右四个方向),如果相邻结点大于该结点,则从该结点到那个相邻结点连接一条边
- 问题转换为求图中的最长路径
- 显然这个图是有向无环图,使用上述的拓扑排序算法求解最长路径