PigyChan_LeetCode 743. 网络延迟时间

743. 网络延迟时间

难度中等

有 N 个网络节点,标记为 1 到 N。
给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。
现在,我们从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1。

示例:
在这里插入图片描述

输入:times = [[2,1,1],[2,3,1],[3,4,1]], N = 4, K = 2
输出:2

注意:
1. N 的范围在 [1, 100] 之间。
2. K 的范围在 [1, N] 之间。
3. times 的长度在 [1, 6000] 之间。
4. 所有的边 times[i] = (u, v, w) 都有 1 <= u, v <= N 且 0 <= w <= 100。

思路1.0:

广度优先遍历,从起点向外扩散,用一个二维数组来存储节点之间的前驱后继关系。

代码1.0(未过):
struct inferTo {
    int target;
    int weight;
    inferTo() :target(0), weight(0) {}
    inferTo(int x, int y) :target(x), weight(y) {}
};
class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        vector<vector<inferTo>> adjacency(N + 1, vector<inferTo>());
        list<inferTo> list_;
        int ans = 0;
        int visitNum = 1;
        //初始化二维矩阵
        for (const auto& i : times) {
            adjacency[i[0]].push_back({ i[1],i[2] });
        }
        //从起点向外广度优先遍历
        for (const auto& i : adjacency[K]) {
            list_.push_back(i);
        }
        while (!list_.empty()) {
            int distance = INT_MAX;
            //找到当前所有能到达目的地的最小距离
            for (const auto& i : list_)
                distance = min(distance, i.weight);
            //减去最小距离
            auto be = list_.begin();
            for (int len = list_.size(); len > 0; --len) {
                (*be).weight -= distance;
                //如果减完了,将该点的所有后继节点加入列表list_,并删掉该节点
                if ((*be).weight == 0) {
                    for (const auto& i : adjacency[(*be).target]) {
                        list_.push_back(i);
                    }
                    list_.erase(be++);
                    visitNum++;
                }
                //如果没减完,遍历下一个
                else
                    be++;
            }
            ans += distance;
            if (visitNum == N) return ans;
        }
        if (visitNum != N) return -1;
        return ans;
    }
};

没考虑到环路的情况,shit!

思路2.0:

通过记录每个节点的前驱个数,并在广度遍历的过程中对其更新,从而来剔除那些已经进入广度优先树的前驱不会重复进入。

思路3.0(已看题解):

Djikstra算法,从所有可选路径中选择最短路径加入图中。具体实现需要如下数据结构:
1)一个二维数组存储每条边的信息,起点,终点,权值
2)一个存储所有节点到起点的最短距离
3)一个存储所有节点是否找到了最短距离

代码2.0:
class Solution {
public:


    int networkDelayTime(vector<vector<int>>& times, int n, int K) {
        vector<vector<int>> djacency(n + 1, vector<int>(n + 1, INT_MAX));
        for (const auto& i : times) {
            djacency[i[0]][i[1]] = i[2];
        }
        vector<long> shortest(n + 1, INT_MAX);
        vector<bool> isShortest(n + 1, false);


        //起点
        shortest[K] = 0;
        //
        for (int i = 0; i < n - 1; ++i) {
            int index = -1;     //用于存储当前可选择路径中的最短路径
            for (int j = 1; j <= n; ++j) {
                if (!isShortest[j] && (index == -1 || shortest[j] < shortest[index])) {
                    index = j;
                }
            }
            isShortest[index] = true;
            //更新shortest值
            for (int j = 1; j <= n; ++j) {
                shortest[j] = min(shortest[j], djacency[index][j]+shortest[index]);
            }
        }


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


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值