###### tags: `Leetcode` `medium` `graph` `heap` `bfs` `python` `c++` # 743. Network Delay Time ## [題目連結:] https://leetcode.com/problems/network-delay-time/ ## 題目: You are given a network of ```n``` nodes, labeled from ```1``` to ```n```. You are also given ```times```, a list of travel times as directed edges ```times[i] = (ui, vi, wi)```, where ```ui``` is the source node, ```vi``` is the target node, and ```wi``` is the time it takes for a signal to travel from source to target. We will send a signal from a given node ```k```. Return the **minimum** time it takes for all the n nodes to receive the signal. If it is impossible for all the ```n``` nodes to receive the signal, return ```-1```. ![](https://i.imgur.com/dHb4kNM.png) ## 解題想法: * 此題為給n個節點,標記為1到n * 給一列表times: times[i] = (ui, vi, wi) * ui:起始點 * vi:結尾點 * wi:傳遞時間(權重) * 求某點k發出信號,多快能使所有節點均能收到 * 若不能使所有節點收到,return -1 * **Dijkstra**: 單源最短路徑(單個點到任一點的最短路徑) * 使用限制: * 權重不可有負 * 不能出現負環 * 流程: * Step1: 建立邊 ``` python= edge=defaultdict(list) for i in range(len(times)): u,v,weight=times[i] edge[u].append((v,weight)) ''' 表示: u--------->v weight ''' ``` * Step2: 初始需要用的工具 * visited=set() :紀錄已拜訪過的點 * que=[(0,k)]: (距離,點) * que使用**heap**,因為可以pop出來每次距離最短的 * Step3: BFS遍歷que * 1. heapque每次選出que中權重最小的出來 * 2. 判斷是否已拜訪過 * 3. 將當前權重更新其連接的鄰居節點,並將鄰居節點加入que ``` python= while que: cur_dis,node=heappop(que) #pop出最短距離的更新 if node in visited: continue visited.add(node) if len(visited)==n: return cur_dis #最後pop出來 且不重複 表示他是最遠點中最短ㄉ距離 for neiber,weight in edge[node]: heappush(que,(cur_dis+weight,neiber)) return -1 ``` ## Python: * **heapq**:為min_heap ``` python= from collections import defaultdict from heapq import heappop, heappush class Solution(object): def networkDelayTime(self, times, n, k): """ :type times: List[List[int]] :type n: int :type k: int :rtype: int """ #用dijkstra #建立邊 edge=defaultdict(list) for i in range(len(times)): u,v,weight=times[i] edge[u].append((v,weight)) #bfs: 找與k最遠點的最短距離 visited=set() #紀錄已拜訪過的點 #用heap來裝 因為可以pop出來每次距離最短的 que=[(0,k)] #(距離,點) while que: cur_dis,node=heappop(que) #pop出最短距離的更新 if node in visited: continue visited.add(node) if len(visited)==n: return cur_dis #最後pop出來 且不重複 表示他是最遠點中最短ㄉ距離 for neiber,weight in edge[node]: heappush(que,(cur_dis+weight,neiber)) return -1 times =[[1,2,1],[2,3,2],[1,3,4]] n=3 k=1 result=Solution() ans=result.networkDelayTime(times,n,k) print(ans) ``` ## C++: * priority_queue:為max_heap * 最頂端要用top(),而非front() ``` cpp= #include<bits/stdc++.h> using namespace std; class Solution { public: int networkDelayTime(vector<vector<int>>& times, int n, int k) { unordered_map<int, vector<pair<int, int>> > edge; //connected the graph for (int i=0; i<times.size(); i++){ int u=times[i][0], v=times[i][1], w=times[i][2]; edge[u].push_back({v,-w}); } set<int> visited; priority_queue<pair<int, int>> que; //max_heap que.push({0,k}); //bfs while (!que.empty()){ pair<int, int> curItem=que.top(); que.pop(); int curDis=curItem.first, node=curItem.second; if (visited.count(node)) // if node already exist in visited continue; visited.insert(node); if (visited.size()==n) return -curDis; //upload neighber for (auto item: edge[node]){ int neighber=item.first, weight=item.second; que.push({(curDis+weight), neighber}); } } return -1; } }; ```