[LeetCode] LeetCode中与有向图相关的题目总结

文章目录

  • 相关题
  • 743. 网络延迟时间

相关题

LeetCode中有向图相关的题的题号为:743,685,684,399,332,310,210

743. 网络延迟时间

有 N 个网络节点,标记为 1 到 N。

给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。

现在,我们从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1。
[LeetCode] LeetCode中与有向图相关的题目总结_第1张图片
解题思路:本题本质上在考察最短路径算法,最短路径算法有单源最短路,多源最短路,然后还掺杂着有权,无权,有向,无向。单源最短路有Dijkstra算法,贝尔福特慢算法(Bellman-Ford Algorithm),Dijkstra算法是模仿图的广度优先遍历(BFS)写的,类似水滴荡起的纹波、迷宫找路等场景。Dijkstra算法首先维护一个dist数组参与松弛操作(Relaxation),当dist[u]>dist[v]+e[u,v],更新路径值dist[u]=dist[v]+e[u,v],防止重复搜索,用visited数组标记已访问过的节点。此题解法我和Grandyang的解法大致相同,但是我的visited数组作为全局变量时,有一半的test case无法通过,不太理解为什么visited作为局部变量就能AC,我在 考虑这个问题的时候思考的方向是,想象水滴荡起纹波的场景,visited作为局部变量,最直接的表象是防止同一层的节点再次被访问,但是将visited作为全局变量,也能达到这个效果,而且也没有干扰dist[u]的更新(之前干过,将visited数组先于dist[u]关系的判断,导致有些节点当放置靠后的位置访问时,能使dist[u]更小),想到这,思路就短路了,接不上了,日后看到此题再思考╮(╯▽╰)╭

在不完全理解此题解法时,也当记住最短路在应用Dijkstra算法时,将visited数组放在层内判断的一种写法。

class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        unordered_map<int, vector<pair<int, int>>> g;
        for (auto t : times) {
            g[t[0]].push_back({t[1], t[2]});
        }
        vector<int> dist(N + 1, INT_MAX);
        
        queue<int> q{{K}};
        dist[K] = 0;
        while (!q.empty()) {
            unordered_set<int> visited;
            for (int i = q.size(); i > 0; --i) {
                int node = q.front(); q.pop();
                for (auto t : g[node]) {
                    if (dist[t.first] > dist[node] + t.second) {
                        dist[t.first] = dist[node] + t.second;
                        if (!visited.count(t.first)) {
                            visited.insert(t.first);
                            q.push(t.first);
                        }
                    }
                }
            }
        }
        int res = 0;
        for (int i = 1; i <= N; ++i) {
            res = max(res, dist[i]);
        }
        return res == INT_MAX ? -1 : res;
    }
};

Bellman-Ford算法近似于暴力解法,暴力美学,针对所有的点,对存在的边都进行遍历一次,对已经连接到K点的u节点进行松弛操作。

class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        int res = 0;
        vector<int> dist(N + 1, INT_MAX);
        dist[K] = 0;
        for (int i = 1; i < N; ++i) {
            for (auto time : times) {
                int u = time[0], v = time[1], w = time[2];
                if (dist[u] != INT_MAX && dist[v] > dist[u] + w) {
                    dist[v] = dist[u] + w;
                }
            }
        }
        for (int i = 1; i <= N; ++i) {
            res = max(res, dist[i]);
        }
        return res == INT_MAX ? -1 : res;
    }
};

你可能感兴趣的:(leetcode)