Hard
Related Topics: Graph / Heap (Priority Queue) / Shortest Path
LeetCode Source
首先,程式建立一個鄰接表來表示圖,並初始化一個二維陣列 distances 來存儲從起點到每個節點的最短距離。
接著,它運行兩次 Dijkstra 演算法,第一次計算當所有未知權重的邊設為 1 時的最短路徑,第二次則考慮調整邊權重,使得最短路徑符合目標值。
若無法達成,返回空集合;若能達成,則返回修改後的邊集合。
在 Dijkstra 演算法中,優先佇列被用來動態更新每個節點的最短距離。
對於那些未知的邊權重,根據需要進行調整,以滿足最終的目標值。
Time Complexity: O((E+V)V)
Space Complexity: O(E+V)
class Solution:
def modifiedGraphEdges(self, n, edges, source, destination, target):
adjacency_list = [[] for _ in range(n)]
for i, (nodeA, nodeB, weight) in enumerate(edges):
adjacency_list[nodeA].append((nodeB, i))
adjacency_list[nodeB].append((nodeA, i))
distances = [[float('inf')] * 2 for _ in range(n)]
distances[source][0] = distances[source][1] = 0
self.run_dijkstra(adjacency_list, edges, distances, source, 0, 0)
difference = target - distances[destination][0]
if difference < 0:
return []
self.run_dijkstra(adjacency_list, edges, distances, source, difference, 1)
if distances[destination][1] < target:
return []
for edge in edges:
if edge[2] == -1:
edge[2] = 1
return edges
def run_dijkstra(self, adjacency_list, edges, distances, source, difference, run):
n = len(adjacency_list)
priority_queue = [(0, source)]
distances[source][run] = 0
while priority_queue:
current_distance, current_node = heapq.heappop(priority_queue)
if current_distance > distances[current_node][run]:
continue
for next_node, edge_index in adjacency_list[current_node]:
weight = edges[edge_index][2]
if weight == -1:
weight = 1
if run == 1 and edges[edge_index][2] == -1:
new_weight = difference + distances[next_node][0] - distances[current_node][1]
if new_weight > weight:
edges[edge_index][2] = weight = new_weight
if distances[next_node][run] > distances[current_node][run] + weight:
distances[next_node][run] = distances[current_node][run] + weight
heapq.heappush(priority_queue, (distances[next_node][run], next_node))
class Solution {
public:
vector<vector<int>> modifiedGraphEdges(int n, vector<vector<int>>& edges, int source, int destination, int target) {
vector<vector<pair<int, int>>> adjacencyList(n);
for (int i = 0; i < edges.size(); i++) {
int nodeA = edges[i][0], nodeB = edges[i][1];
adjacencyList[nodeA].emplace_back(nodeB, i);
adjacencyList[nodeB].emplace_back(nodeA, i);
}
vector<vector<int>> distances(n, vector<int>(2, INT_MAX));
distances[source][0] = distances[source][1] = 0;
runDijkstra(adjacencyList, edges, distances, source, 0, 0);
int difference = target - distances[destination][0];
if (difference < 0) return {};
runDijkstra(adjacencyList, edges, distances, source, difference, 1);
if (distances[destination][1] < target) return {};
for (auto& edge : edges) {
if (edge[2] == -1) edge[2] = 1;
}
return edges;
}
private:
void runDijkstra(const vector<vector<pair<int, int>>>& adjacencyList, vector<vector<int>>& edges, vector<vector<int>>& distances, int source, int difference, int run) {
int n = adjacencyList.size();
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> priorityQueue;
priorityQueue.push({0, source});
distances[source][run] = 0;
while (!priorityQueue.empty()) {
auto [currentDistance, currentNode] = priorityQueue.top();
priorityQueue.pop();
if (currentDistance > distances[currentNode][run]) continue;
for (auto& neighbor : adjacencyList[currentNode]) {
int nextNode = neighbor.first, edgeIndex = neighbor.second;
int weight = edges[edgeIndex][2];
if (weight == -1) weight = 1;
if (run == 1 && edges[edgeIndex][2] == -1) {
int newWeight = difference + distances[nextNode][0] - distances[currentNode][1];
if (newWeight > weight) {
edges[edgeIndex][2] = weight = newWeight;
}
}
if (distances[nextNode][run] > distances[currentNode][run] + weight) {
distances[nextNode][run] = distances[currentNode][run] + weight;
priorityQueue.push({distances[nextNode][run], nextNode});
}
}
}
}
};
static const auto mynameisbarryallen = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();