题目链接:https://ac.nowcoder.com/acm/contest/52431/J

思路:以1号节点走单源最短路,答案为两个询问点单源最短路之和,若使用另一种方法即SPFA理论得不到全部的分数!!

代码实现:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 100007, M = 100007 << 1;
int n, m;
vector<pair<int, int>> g[N];//邻接表存取无向有权图
bool vis[N];  //记录类似bfs节点是否走过
ll dis[N];
struct node {      
    int v;
    ll w;
    friend bool operator<(const node &a, const node &b) {  //重载小于号比较的是两个节点的权值
        return a.w > b.w;
    }
};
priority_queue<node> pq;//优先队列(小根堆)存取
void dijkstra(int st) {
    for (int i = 1;i <= n;i++) dis[i] = 1e18; //目前求最短路,故首先将每一个节点的距离赋值为一个极大值
    dis[st] = 0;   //初始设为0,距离从0开始加,起始节点为st
    pq.push({ st,0 }); //类似bfs基本思路,首先给优先队列中放入第一个元素
    while (!pq.empty()) {
        int u = pq.top().v; //bfs基本操作
        pq.pop();
        if (vis[u]) continue;//如果遍历过该点,跳出此循环
        vis[u] = 1;
        for (auto [v, w] : g[u]) {//利用C++17的auto快速遍历邻接表(遍历节点u的所有邻居)
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;     //获取节点u到某一个节点最近的最短路长度
                pq.push({ v,dis[v] });  //继续遍历节点v同u一样,获取v的最短路
            }
        }//直至遍历到终点即已经没有邻居,所有的点都遍历到了,
    }
}


int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);//加快程序的执行速度
    cin >> n >> m;
    for (int i = 1;i <= m;i++) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back({ v,w });
        g[v].push_back({ u,w });//无向图基本赋值方法,均赋值u->v,v->u
    }
    dijkstra(1);//从1号节点进行单源最短路遍历
    int T;
    cin >> T;
    while (T--) {
        int s, t;
        cin >> s >> t;
        cout << dis[s] + dis[t] << '\n';   //由题意必须经过节点1,所以和为总的最短路
    }
    return 0;
}