1. 程式人生 > >Network Delay Time 網路延遲時間

Network Delay Time 網路延遲時間

有 N 個網路節點,標記為 1 到 N

給定一個列表 times,表示訊號經過有向邊的傳遞時間。 times[i] = (u, v, w),其中 u 是源節點,v 是目標節點, w 是一個訊號從源節點傳遞到目標節點的時間。

現在,我們向當前的節點 K 傳送了一個訊號。需要多久才能使所有節點都收到訊號?如果不能使所有節點收到訊號,返回 -1

注意:

  1. N 的範圍在 [1, 100] 之間。
  2. K 的範圍在 [1, N] 之間。
  3. times 的長度在 [1, 6000] 之間。
  4. 所有的邊 times[i] = (u, v, w) 都有 1 <= u, v <= N 且 1 <= w <= 100

思路:這道題其實就是單源最短路勁的問題(即在圖中給定節點K,其他所有節點距離K的距離),主要解法有Dijkstra’s algorithm和Bellman–Ford Algorithm解法。接下來分別說下:

思路一:迪傑斯特拉解法,最常見的解法是不使用任何輔助,類似於BFS每次向外拓展一圈。時間複雜度O(n^2),n表示節點。

參考程式碼:

class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
	if (times.empty()) return -1;
	vector<vector<int>> edges(101, vector<int>(101,-1));
	vector<int> dict(N + 1, INT_MAX);
	dict[K] = 0;
	queue<int> q; q.push(K);
	for (auto time : times) edges[time[0]][time[1]] = time[2];
	while (!q.empty()) {
		unordered_set<int> visited;
		for (auto i = q.size(); i > 0; i--) {
			auto u = q.front(); q.pop();
			for (int v = 1; v <= 100; v++) {
				if (edges[u][v] != -1 && dict[v] > (dict[u] + edges[u][v])) {
					if (!visited.count(v)) {
						visited.insert(v);
						q.push(v);
					}
					dict[v] = (dict[u] + edges[u][v]);
				}
			}
		}	
	}
	int res = 0;
	for (int i = 1; i <= N; i++) {
		if (dict[i] == INT_MAX) return -1;
		res = max(res, dict[i]);
	}
	return res;    
    }
};

思路二:採用了最小堆,每次從堆中取出距離最短的節點,時間複雜度為O(vlogv)。

參考程式碼:

class Solution {
public:
struct networkDelayTimeCmp {
	bool operator()(const pair<int, int> &a, const pair<int, int> &b) {
		return a.second > b.second;
	}
};

unordered_map<int, vector<vector<int>>> make_graph(vector<vector<int>>& times, int N) {
	unordered_map<int, vector<vector<int>>> res;
	for (auto node : times) {
		if (res.find(node[0]) == res.end()) res[node[0]] = { {node[1],node[2]} };
		else {
			vector<vector<int>> old = res[node[0]];
			old.push_back({ node[1],node[2] });
			res[node[0]] = old;
		}
	}
	return res;
}
int networkDelayTime(vector<vector<int>>& times, int N, int K) {
	if (times.empty()) return -1;
	priority_queue<pair<int, int>, vector<pair<int, int>>, networkDelayTimeCmp> q;
	unordered_map<int, vector<vector<int>>> map = make_graph(times, N);
	vector<int> dict(N+1,INT_MAX);
	dict[K] = 0;
	q.push({K,0});
	while (!q.empty()) {
		auto closest = q.top(); q.pop();
		if (map.find(closest.first) != map.end()) {
			for (auto neibors : map[closest.first]) {
				int v = neibors[0];
				int weight = neibors[1];
				int u = closest.first;
				if ((long)(dict[v]) > (long)(dict[u] + weight)) {
					dict[v] = (dict[u] + weight);
					q.push({v,dict[v]});
				}
			}
		}
	}
	int res = 0;
	for (int i = 1; i <= N;i++) {
		if (dict[i]==INT_MAX) {
			return -1;
		}
		res = max(res, dict[i]);
	}
	return res;
}
};

思路三:最後是bellman演算法,時間複雜度為O(vloge)(v表示節點,e表示邊)

參考程式碼:

class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
	if (times.empty()) return -1;
	vector<int> dict(N + 1, INT_MAX);
    dict[K]=0;
	for (int i = 1; i < N; i++) {
		for (auto time : times) {
			int u = time[0], v = time[1], w = time[2];
			if (dict[u] != INT_MAX && dict[v] > (dict[u] + w)) {
				dict[v] = dict[u] + w;
			}
		}
	}
	int res = 0;
	for (int i = 1; i <= N; i++) {
		if (dict[i] == INT_MAX) return -1;
		res = max(res, dict[i]);
	}
	return res;        
    }
};