#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;
}