LeetCode第 743 题:网络延迟时间(C++)

743. 网络延迟时间 - 力扣(LeetCode)

计算的是要是所有节点都接收到信号经历的时长,所以必然是需要遍历整个图的,并且遍历的时候需要记录每个节点接收到信号经历的时长,时长也就是该节点到起始节点 K 的最短路径长度。

那么我们可以使用dijkstra算法计算每个节点到起始节点 K 的最短路径,最后取所有路径中最大的那个即可。

数据结构与算法:44 |最短路径:地图软件如何计算最优出行路径?_zj-CSDN博客

引入两个集合 S 和 U,S 的作用是记录已求出最短路径的顶点(以及相应的最短路径长度,可以使用pair),而U的作用记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。

初始情况下,S中只有起点 K(对应最短路径为0,自己到自己);U中是除 K 之外的所有顶点,并且U中顶点的路径是: 起点 K 到该顶点的路径(初始化为 INT_MAX)。

while循环里主要做两件事:

  • 找到未处理节点(集合 U)中距离起点路径值最小的节点,同时将该顶点加入集合 S,并从集合 U中移除该顶点。
  • 更新 U 中的顶点到起点 K 的记录。

直到遍历完所有顶点,循环结束。

对于寻找最小路径值这一操作,可以使用优先级队列进行优化:

class Solution {
public:
    int networkDelayTime(vector>& times, int N, int K) {
        vector distance(N+1, INT_MAX);//起点K到每个节点的距离
        vector flags(N+1, false);//记录节点是否已经计算出最短距离
        unordered_map>> adj;//邻接表
        //piar第一个为距离,第二个为节点编号
        for(const auto &v : times)  adj[v[0]].push_back({v[2], v[1]});//生成邻接表

        //小顶堆,pair第一个元素为节点K到该节点的距离,第二个是该节点的编号
        priority_queue, vector>, greater>> q;
        
        q.push({0, K});
        distance[K] = 0;//自己到自己的距离为0
        while(!q.empty()){
            auto t = q.top();
            q.pop();
            int cur = t.second, dis = t.first;//cur表示当前节点,dis表示节点K到当前节点的距离
            
            if(dis == INT_MAX)  return -1;//队列头部最小值也为INT_MAX,说明信号无法达到
            if(flags[cur])   continue;//之前处理过
            flags[cur] = true;
            //考虑与当前节点cur相连(指向)的节点,并更新节点K到他们的距离
            for(const auto &p : adj[cur]){//adj[cur]映射到vector>
                //找到更短的距离,需要更新
                if(distance[p.second] > dis + p.first){//dis(p.second, k) > dis(k, cur) + dis(cur, p.second),dis代表两者距离
                    distance[p.second] = dis + p.first; 
                    q.push({distance[p.second], p.second});//{K到该节点的距离,该节点的编号}
                }
            }
        }

        int res = *max_element(distance.begin()+1, distance.end());
        return res == INT_MAX ? -1 : res;
    }
};

如果不使用优先级队列,需要手动寻找最小值,不过思路都是一样的:

class Solution {
public:
    int networkDelayTime(vector>& times, int N, int K) {
        vector distance(N+1, INT_MAX);//起点K到每个顶点的距离
        vector flags(N+1, false);//记录顶点是否已经计算出最短距离
        unordered_map>> adj;//邻接表
        //piar第一个为距离,第二个为节点编号
        for(const auto &v : times)  adj[v[0]].push_back({v[2], v[1]});//生成邻接表
        
        distance[K] = 0;//自己到自己的距离为0
        for(int i = 0; i < N-1; ++i){//循环次数最多为N-1次(因为起点k已激活)
            //遍历所有的顶点,寻找距离起点的距离最小的那个
            int t = -1;
            for(int j = 1; j <= N; ++j){//编号从1开始,第一位没有使用
                if(!flags[j] && (t == -1 || distance[t] > distance[j])) t = j;
            }
            flags[t] = true; //该顶点的最短路径已确定

            //更新与顶点t相连的节点到起点的距离,其他不相连的顶点不用更新
            for(const auto &p : adj[t]){
                if(distance[p.second] > distance[t] + p.first){
                    distance[p.second] = distance[t] + p.first;
                }
            }
        }
        int res = *max_element(distance.begin()+1, distance.end());
        return res == INT_MAX ? -1 : res;
    }
};

优化一下:

class Solution {
public:
    int networkDelayTime(vector>& times, int N, int K) {
        vector distance(N+1, INT_MAX);//起点K到每个顶点的距离
        vector flags(N+1, false);//记录顶点是否已经计算出最短距离
        unordered_map>> adj;//邻接表
        //piar第一个为距离,第二个为节点编号
        for(const auto &v : times)  adj[v[0]].push_back({v[2], v[1]});//生成邻接表
        
        distance[K] = 0;//自己到自己的距离为0
        for(int i = 0; i < N; ++i){//循环次数最多为N-1次(因为起点k已激活)
            //遍历所有的顶点,寻找距离起点的距离最小的那个
            int t = -1;
            for(int j = 1; j <= N; ++j){//编号从1开始,第一位没有使用
                if(!flags[j] && (t == -1 || distance[t] > distance[j])) t = j;
            }
            flags[t] = true; //该顶点的最短路径已确定
            if(distance[t] == INT_MAX)  return -1;//最小值为INT_MAX,说明剩下的顶点都不可能和起点相连,永远接收不到信号
            //更新与顶点t相连的节点到起点的距离,其他不相连的顶点不用更新
            for(const auto &p : adj[t]){
                if(distance[p.second] > distance[t] + p.first){
                    distance[p.second] = distance[t] + p.first;
                }
            }
        }
        return *max_element(distance.begin()+1, distance.end());
    }
};

你可能感兴趣的:(leetcode,leetcode)