【无标题】

很明显的最短路径问题,仅改变最短路径的意义为

即可max(minDist[cur] , c) < minDist[to]

朴素的迪杰斯特拉:

#include 
#include
using namespace std;
int n, m;
struct Edge {
    int to;
    int c;
    Edge(int to, int c) :to(to), c(c) {}
};
void work(vector> grid) {
    //记录源结点到每个节点的最短距离
    vector minDist(n + 1, INT_MAX);
    //记录哪些结点已经被访问过
    vector visited(n + 1, false);
    //初始化
    minDist[1] = 0;
    //遍历n次 加入n个结点
    for (int i = 1; i <= n; i++) {
        //找到距离原点最近的结点
        int cur = 1;
        int minVal = INT_MAX;
        for (int v = 1; v <= n; v++) {
            if (!visited[v] && minDist[v] < minVal) {
                cur = v;
                minVal = minDist[v];
            }
        }
        //标记结点被访问过
        visited[cur] = true;
        //更新结点距离
        for (Edge e : grid[cur]) {
            int to = e.to;
            int c = e.c;
            if (!visited[to] && max(minDist[cur] , c) < minDist[to]) {
                minDist[to] = max(minDist[cur], c);
            }
        }
    }
    cout << minDist[n];

}
int main() {
    //n:交通枢纽的数量
    //m:候选隧道的数量
    cin >> n >> m;
    vector> grid(n + 1);
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        grid[a].push_back(Edge(b, c));
        grid[b].push_back(Edge(a, c));
    }
    work(grid);
    return 0;
}

堆优化的迪杰斯特拉(从边的角度出发):

#include 
#include
using namespace std;
int n, m;
struct Edge {
    int to;
    int c;
    Edge(int to, int c) :to(to), c(c) {}
};
// 小顶堆
class mycomparison {
public:
    bool operator()(const pair& lhs, const pair& rhs) {
        return lhs.second > rhs.second;
    }
};

void work(vector> grid) {
    //记录源结点到每个节点的最短距离 
    vector minDist(n + 1, INT_MAX);
    //记录哪些结点已经被访问过
    vector visited(n + 1, false);
    //优先队列储存边
    priority_queue, vector>, mycomparison> pq;
    //初始化
    minDist[1] = 0;  // 起始点到自身的距离为0
    // 初始化队列,源点到源点的距离为0,所以初始为0
    pq.push(pair(1, 0));
    //遍历n次 加入n个结点
    while (!pq.empty()) {
        // 1. 第一步,选源点到哪个节点近且该节点未被访问过 (通过优先级队列来实现)
// <节点, 源点到该节点的距离>
        pair cur = pq.top(); pq.pop();

        if (visited[cur.first]) continue;

        // 2. 第二步,该最近节点被标记访问过
        visited[cur.first] = true;

        // 3. 第三步,更新非访问节点到源点的距离(即更新minDist数组)
        for (Edge edge : grid[cur.first]) { // 遍历 cur指向的节点,cur指向的节点为 edge
            // cur指向的节点edge.to,这条边的权值为 edge.val
            if (!visited[edge.to] && max(minDist[cur.first] ,edge.c) < minDist[edge.to]) { // 更新minDist
                minDist[edge.to] = max(minDist[cur.first], edge.c);
                pq.push(pair(edge.to, minDist[edge.to]));
            }
        }
    }
    cout << minDist[n];

}
int main() {
    //n:交通枢纽的数量
    //m:候选隧道的数量
    cin >> n >> m;
    vector> grid(n + 1);
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        grid[a].push_back(Edge(b, c));
        grid[b].push_back(Edge(a, c));
    }
    work(grid);
    return 0;
}

你可能感兴趣的:(CCF-CSP,算法,数据结构)