[Week 4] LeetCode 743. Network Delay Time

15 篇文章 0 订阅
13 篇文章 0 订阅

LeetCode 743. Network Delay Time

问题描述:

There are N network nodes, labelled 1 to N.

Given times, a list of travel times as directed edges times[i] = (u, v, w), where u is the source node, v is the target node, and w is the time it takes for a signal to travel from source to target.

Now, we send a signal from a certain node K. How long will it take for all nodes to receive the signal? If it is impossible, return -1.

Note:

  1. N will be in the range [1, 100].
  2. K will be in the range [1, N].
  3. The length of times will be in the range [1, 6000].
  4. All edges times[i] = (u, v, w) will have 1 <= u, v <= N and 1 <= w <= 100.

题解:

很容易看出这是一个单源最短路径问题,只需要求出从原点K到图中其它点的最短路径,然后找到其中最长的即为题解,当然结果出现infinite意味着该图不连通,返回-1即可。

这类问题的求解,我们需要知道一个信息:是否会有负权边出现?OK,这道题边权代表时间,所以不会出现。对于无负边权的单源最短路径问题,我们很容易想到Dijkstra算法,那什么是Dijkstra算法呢?

Dijkstra 算法:

给定一个有向图G(V,E),我们一开始初始化一个dist数组(dist[i]指源点A到顶点i的距离),除了源点为0,其它顶点设置为infinite

  1. 我们从源点A开始,找到与源点相连的顶点,通过遍历以A为起点的边,更新dist数组,即设置源点到其直接相连点的距离。
    在这里插入图片描述
  2. 然后找到dist数组里除 源点Adist[i]最小的顶点:C,通过遍历以C为起点的边,更新dist数组。
    在这里插入图片描述
  3. 接着找到dist 数组里除 源点A 和 C 外dist[i]最小的顶点:B,通过遍历以B为起点的边,更新dist`数组。
    在这里插入图片描述
  4. 后面DE交给读者自己分析,看看最后的结果:
    在这里插入图片描述
# 伪代码
Input:G(V, E) -- a directed graph with vertices collection V and edges collection E
Output: For all vertices u reachable from source s, dist(u) is the distance from s to u

for all u in V:
	dist(u) = infinite
dist(s) = 0

# 使用优先队列找到值最小的点
Q = makequeue(V) (use dist as keys)
while Q is not empty:
	u = Q.pop()
	for all e(u,v) in E:
		if dist(v) > dist(u) + l(u,v):
			dist(v) = dist(u) + l(u,v)
			decreaseKey(Q,v)  # 让队列中元素重新排列

代码:

#include <vector>
#include <queue>
#include <climits>

using namespace std;

typedef pair<int, int> node;

int networkDelayTime(vector<vector<int> > &times, int N, int K)
{
  /* 
   * initialize the graph :
   * nodes are labelled 1 to N, so we let index start from 1 not 0 
   */
  vector<vector<int> > graph(N + 1, vector<int>(N + 1, -1));
  for (int i = 0; i < times.size(); ++i)
  {
    vector<int> &e = times[i];
    graph[e[0]][e[1]] = e[2];
  }

  /*
   * dist[i] means distance of (K, i), INT_MAX means disconnected
   * visited[i] means node has been closed or not 
   */
  vector<int> dist(N + 1, INT_MAX);
  vector<bool> visited(N + 1, false);
  dist[K] = 0;

  priority_queue<node, vector<node>, greater<node> > que;
  que.push(node(dist[K], K));
  while (!que.empty())
  {
    node u = que.top();
    que.pop();
    int u_num = u.second;
    if (visited[u_num])
      continue;

    for (int i = 1; i < graph[u_num].size(); ++i)
    {
      if (graph[u_num][i] != -1 && dist[i] > dist[u_num] + graph[u_num][i])
      {
        dist[i] = dist[u_num] + graph[u_num][i];
        if (!visited[i])
          que.push(node(dist[i], i));
      }
    }
  }

  int result = 0;
  for (int i = 1; i <= N; ++i)
  {
    if (dist[i] == INT_MAX)
      return -1;
    else
      result = max(result, dist[i]);
  }
  return result;
}

复杂度分析:

首先考虑一下不使用优先队列的情况,每次我们都需要找到dist数组中值最小的点,复杂度为O(|V|);然后遍历以该点为起点的边,所以算法结束会遍历所有的边,即O(|E|);总共需要遍历|V|次,所以总时间复杂度为 O(|V|^2)

使用优先队列的情况,考虑应用二分堆实现的优先队列。取出dist中最小值点,因为删除节点都会导致堆的结构调整,复杂度为O(log|V|);遍历每条边时,因为dist[i]值的变化,需要调整堆的结构,复杂度为O(log|V|);总的来说,大概需要|V|次取最小值点,|E|次改变 dist[i]的值,所以总复杂度为 O((|V|+|E|)log(|V|))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值