Week3

Week4

上周犯了个小错误,在写第3周的博客时,不小心直接在第2周的博客上改了,然后第2周的博客直接被第3周的覆盖了,所以这周写2篇补回来。
Graph
question source: Network Delay Time

question description

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.

这周学习了图的路径,这是一个有向图类型的题目,问的是从图中的一个点,发出一个信号,要多长时间,所有点能收到信号。很明显,这就是求一个点到其他点的最短距离,而这些距离中的最大值,就是我们要求的。很明显就是用这周学的迪杰斯特拉算法,下面就些实现了这个算法。
迪杰斯特拉算法伪代码如下

Function Dijkstra(G, w, s)
	for each vertex v in V[G]				
		d[v] := infinity							// 开始最短距离设为无穷
		previous[v] := undefined			// 用于保存前一个节点
	d[s] := 0										// 出发点到出发点的距离为0
	S := empty set
	Q := set of all vertices
	while Q is not an empty set
		u := Ectract_Min(Q)					// 把集合Q里的距离最小的删除
		S.append(u)
		for each edge outgoing from u as (u, v)
			if d[v] > d[u] + w(u, v)			// 更新
				d[v] := d[u] + w(u, v)
				previous[v] := u   

实现的代码如下

class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        //dijkstra
        int dist[N + 1];
        int q[N + 1];
        for(int i = 1; i <= N; i++){
            dist[i] = -1;
            q[i] = 1;
        }
        dist[K] = 0;
        //S:empty
        //Q: all set
        int n = N;
        while(n != 0){
            int v = 0;
            //find min dist
            int min = -1;
            for(int i = 1; i <= N; i++){
                if(q[i] == 1){
                    if(min == -1 && dist[i] != -1){
                        min = dist[i];
                        v = i;
                    }else if(dist[i] < min && dist[i] != -1){
                        min = dist[i];
                        v = i;
                    }
                }
            }
            //The grap is not connected
            if(v == 0) return -1;
            for(int i = 0; i < times.size(); i++){
                
                if(times[i][0] == v){
                    int next = times[i][1];
                    if(dist[next] == -1){
                        dist[next] = times[i][2] + dist[v];
                    }else if(dist[next] > times[i][2] + dist[v]){
                        dist[next] = times[i][2] + dist[v]; 
                    }
                }
            }
            
            q[v] = 0;
            n--;
        }
        
        int answer = 0;
        for(int i = 1; i <= N; i++){
            if(dist[i] > answer){
                answer = dist[i];
            }
        }
        return answer;
    }
};

迪杰斯特拉算法要求我们实现一个优先队列,算法运行时间严重依赖于优先队列的实现方式。我的代码是使用一个无序数组q来实现,insert操作或者decreasekey操作是很快的,只要修改一个键值就行了,耗费的时间是O(1),而deletemin操作需要对整个数组进行扫描,从而将耗费线性时间。总的算法复杂度为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2)

上课说了,优先队列也可以采用二分堆来实现。元素存储在一个完全二叉树上,树中任意节点的键值必须小于等于其后裔节点的键值。insert时,将元素置于树的最底端,然后让它“冒泡”,decreasekey时,从当前位置直接“冒泡”,而deletemin时,直接返回根节点的键值。删除根节点后,取出树的最后一个节点,置于树根,然后“向下过滤”。完全二叉树直接用数组实现,总的算法复杂度为 O ( ( ∣ V ∣ + ∣ E ∣ ) l o g ∣ V ∣ ) O((|V| + |E|)log|V|) O((V+E)logV)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值