845 字
4 分钟
多层最短路
#include <iostream>#include <vector>#include <limits>#include <tuple>#include <cstdlib>#include <chrono>#include <algorithm> // 用于 make_heap, push_heap, pop_heap#include <unordered_map>
using namespace std;
// 定义一个常量表示无穷大const int INF = numeric_limits<int>::max();
// 定义一个结构体表示图中的边struct Edge { int to; // 目标节点 int cost; // 边的代价};
// 自定义二叉堆class BinaryHeap {public: using Element = tuple<int, int, int>; // (当前代价, 当前层, 当前节点)
// 插入元素 void push(const Element& element) { heap.push_back(element); push_heap(heap.begin(), heap.end(), compare); }
// 弹出最小元素 void pop() { pop_heap(heap.begin(), heap.end(), compare); heap.pop_back(); }
// 获取最小元素 Element top() const { return heap.front(); }
// 判断堆是否为空 bool empty() const { return heap.empty(); }
private: vector<Element> heap;
// 比较函数,用于实现最小堆 static bool compare(const Element& a, const Element& b) { return get<0>(a) > get<0>(b); // 按代价升序排列 }};
// 修改后的 Dijkstra 算法using InterLayerConnections = vector<unordered_map<int, vector<pair<int, int>>>>;
void dijkstra(int startLayer, int startNode, const vector<vector<vector<Edge>>>& graph, const InterLayerConnections& interLayerCost, vector<vector<int>>& minCost) { int layers = graph.size(); int nodes = graph[0].size();
// 自定义二叉堆,存储 (当前代价, 当前层, 当前节点) BinaryHeap pq;
// 初始化最小代价数组 for (int i = 0; i < layers; ++i) { fill(minCost[i].begin(), minCost[i].end(), INF); }
// 将起始节点加入队列 minCost[startLayer][startNode] = 0; pq.push({ 0, startLayer, startNode });
// Dijkstra 主循环 while (!pq.empty()) { auto [currentCost, currentLayer, currentNode] = pq.top(); pq.pop();
// 如果当前代价大于已记录的最小代价,跳过 if (currentCost > minCost[currentLayer][currentNode]) continue;
// 遍历当前层的邻接节点 for (const auto& edge : graph[currentLayer][currentNode]) { int nextNode = edge.to; int nextCost = currentCost + edge.cost;
if (nextCost < minCost[currentLayer][nextNode]) { minCost[currentLayer][nextNode] = nextCost; pq.push({ nextCost, currentLayer, nextNode }); } }
// 遍历层间连接 if (interLayerCost[currentLayer].count(currentNode)) { for (const auto& [nextLayer, cost] : interLayerCost[currentLayer].at(currentNode)) { int nextCost = currentCost + cost; if (nextCost < minCost[nextLayer][currentNode]) { minCost[nextLayer][currentNode] = nextCost; pq.push({ nextCost, nextLayer, currentNode }); } } } }}
int main() { // 示例输入数据 int layers = 240; // 层数 int nodes = 1000; // 每层的节点数
// 每层的图结构 (层 -> 节点 -> 边) vector<vector<vector<Edge>>> graph(layers, vector<vector<Edge>>(nodes));
// 构造每层的边,尽量构造平面图 for (int layer = 0; layer < layers; ++layer) { for (int node = 0; node < nodes; ++node) { // 每个节点连接到下一个节点,形成一个环 int nextNode = (node + 1) % nodes; graph[layer][node].push_back({ nextNode, rand() % 10 + 1 }); // 随机权重1-10
// 添加额外的边,确保每层有5000条边以上 for (int i = 0; i < 5; ++i) { int randomNode = rand() % nodes; if (randomNode != node) { graph[layer][node].push_back({ randomNode, rand() % 10 + 1 }); } } } }
// 定义层间连接关系的稀疏存储结构 InterLayerConnections interLayerCost(layers);
// 构造层间连接代价 for (int layer = 0; layer < layers - 1; ++layer) { for (int node = 0; node < nodes; ++node) { // 只有三分之一的节点有层间连接 if (rand() % 3 == 0) { int cost = rand() % 2000 + 1000; // 随机权重1000-3000 interLayerCost[layer][node].push_back({ layer + 1, cost }); // 当前层到下一层 interLayerCost[layer + 1][node].push_back({ layer, cost }); // 下一层到当前层 } } }
// 最后一层连接回第一层 for (int node = 0; node < nodes; ++node) { if (rand() % 3 == 0) { int lastCost = rand() % 2000 + 1000; // 随机权重10-30 interLayerCost[layers - 1][node].push_back({ 0, lastCost }); // 最后一层到第一层 interLayerCost[0][node].push_back({ layers - 1, lastCost }); // 第一层到最后一层 } }
// 起始节点和层 int startNode = 0; int startLayer = 0;
// 最小代价数组 vector<vector<int>> minCost(layers, vector<int>(nodes, INF));
// 运行Dijkstra算法 auto startTime = chrono::high_resolution_clock::now(); // 开始计时
dijkstra(startLayer, startNode, graph, interLayerCost, minCost);
auto endTime = chrono::high_resolution_clock::now(); // 结束计时 auto duration = chrono::duration_cast<chrono::milliseconds>(endTime - startTime); cout << "Total Dijkstra computation time: " << duration.count() << " ms" << endl;
return 0;}