题意整理:

题目以边的形式给出一个有向图,要求找到图中指定两个点(1,n)中的最短路径
为了便于后续操作,我们先将给出的边权数组转化为点对之间的距离,对于没有边链接的距离为INT_MAX,对于重边取得较小值。

方法一:DFS(超时)

核心思想:

首先,我们需要从起点1开始,往能够前往的点进行搜索。此处需要维持一个vis数组记录哪些点已经进行了访问,如果再次访问将不对其进行访问,因为边权都是正值,明显对一个点再次访问不会得到更好的答案。当到达点n时停止搜索,更新答案。
由于对边的访问没有特殊顺序,所有可能每次都以最差路径为开始进行遍历,时间复杂度很高,无法通过所有测试案例

核心代码:

class Solution {
public:
    int ans, len;

    void dfs(vector<vector<int>>& f, vector<int>& vis, int p, int d) {
        if(p == len) {//找到n点
            ans = min(ans,d);
            return;
        }
        if(d >= ans) {//剪枝
            return;
        }
        vis[p] = d;//记录
        for(int i = 1; i <= len; ++i) {
            if((vis[i] == -1 || vis[i] > d + f[p][i]) && f[p][i] != INT_MAX) {
                //确保不访问已经不会作为答案的路线
                dfs(f, vis, i, d + f[p][i]);
            }
        }
    }

    int findShortestPath(int n, int m, vector<vector<int> >& graph) {
        vector<vector<int>> f(n, vector<int>(n, INT_MAX));//距离数组
        len = n - 1;
        ans = INT_MAX;//初始化答案为最大值
        for(vector<int>& it : graph) {
            f[it[0] - 1][it[1] - 1] = min(f[it[0] - 1][it[1] - 1],it[2]);//填入边权
        }
        vector<int> vis(n, -1);
        dfs(f, vis, 0, 0);
        return ans == INT_MAX ? -1 : ans;
    }
};

复杂度分析:

时间复杂度:。最坏的情况下,会对每个点的边都进行一次搜索,
空间复杂度:,使用了大小为的空间记录边,大小为的空间记录访问情况,以及最坏为的递归栈

方法二:dijkstra算法

核心思想:

方法一之所以会超时,主要在于每次遍历点都只是基于点的编号,没有利用其他性质,可能会出现一个点遍历多次的情况,且每次都需要对大量点进行重新更新。实际上,对于点对之间的距离,有个很好的算法既dijkstra算法。
算法思路:使用一个d数组记录从源点出发到其他点的距离。
初始化 ,其他
循环n次,每次在未标记节点中,选出d值最小的节点 x ,对其打上标记,对于从x出发的所有边(x, y)进行更新,这使得每次更新只对少数点进行更新,且不会对后续点产生影响,因为每次都是选择d最小的点。
图片说明

核心代码:

class Solution {
public:
    int findShortestPath(int n, int m, vector<vector<int> >& graph) {
        vector<vector<int>> f(n, vector<int>(n, INT_MAX));//距离数组
        for(vector<int>& it : graph) {
            f[it[0] - 1][it[1] - 1] = min(f[it[0] - 1][it[1] - 1],it[2]);//填入边权
        }
        vector<int> vis(n, 0);//记录访问情况
        vector<int> d(n, INT_MAX);//记录距离
        d[0] = 0;
        for(int i = 0; i < n; ++i) {
            //遍历n次n个点
            int x = 0, p = INT_MAX;
            for(int y = 0; y < n; ++y) {
                if(vis[y] == 0 && d[y] < p) {
                    //找到最小x值
                    p = d[y];
                    x = y;
                }
            }
            if(p == INT_MAX) {
                //无法继续找到点,结束掉
                break;
            }
            vis[x] = 1;
            for(int y = 1; y < n; ++y) {
                //对点进行更新
                if(f[x][y] != INT_MAX) {
                    d[y] = min(d[y], d[x] + f[x][y]);
                }
            }
        }
        return d[n - 1] == INT_MAX ? -1 : d[n - 1];
    }
};

复杂度分析:

时间复杂度:,遍历了n次,每次选取最小x需要花费时间
空间复杂度:,使用了大小为的空间记录边,大小为的空间记录访问情况,大小为的空间记录距离