用vector数组来存储每个节点的相邻节点
#include<iostream>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1000010;
/*
边尾=====>边头
*/
struct qnode {
int v;//顶点index
int c;//源点到该顶点的最短距离
qnode(int _v = 0, int _c = 0) :v(_v), c(_c) {}
//重载<, 变成最小堆(根据源点到节点的路径长度从大到小排,优先队列中top元素是最小的)
bool operator <(const qnode& r)const {
return c > r.c;
}
};
struct Edge {
int v, cost;//和找到的最短路径节点相邻的顶点,连接这两个顶点边权重
Edge(int _v = 0, int _cost = 0) :v(_v), cost(_cost) {}
};
vector<Edge>AdjList[MAXN];//类似邻接表(边节点以顺序表存储)
bool vis[MAXN];//访问数组
int dist[MAXN];//距离数组
//点的编号从 1 开始
void Dijkstra(int n, int start) { //顶点数,源点
memset(vis, false, sizeof(vis));//访问数组初始化全false
for (int i = 1; i <= n; i++) //距离数组初始化inf
dist[i] = INF;
priority_queue<qnode>que;
dist[start] = 0;
que.push(qnode(start, 0));//源点入队
qnode tmp;
while (!que.empty()) {
tmp = que.top(); //因为重载了<,top节点到源点距离一定是最短的
que.pop();
int u = tmp.v; //找到的最短路径节点的节点号u
if (vis[u]) //判断是否已经访问过了
continue;
vis[u] = true; //设置成已访问
//对当前找到的最短路径节点的边界点组访问(和该节点相邻的节点,用到邻接表知识)
for (int i = 0; i < AdjList[u].size(); i++) {
int v = AdjList[u][i].v; //边头节点
int cost = AdjList[u][i].cost;//边权重
//1.这个节点没被访问
//2.上一轮源节点到该节点的距离>从源点到当前最短路径节点距离+当前最短路径节点到这个节点的距离
if (!vis[v] && dist[v] > dist[u] + cost) {
dist[v] = dist[u] + cost;//更新
que.push(qnode(v, dist[v]));//进入优先队列,为下一轮找最短路径节点做准备
}
}
}
}
//边尾,边头,权重
//向类似邻接表添加边
void addedge(int u, int v, int w) {
AdjList[u].push_back(Edge(v, w));
}
int main() {
addedge(1, 3, 8);
addedge(3, 4, 5);
addedge(4, 5, 6);
addedge(1, 2, 13);
addedge(2, 6, 9);
addedge(2, 7, 7);
addedge(1, 5, 30);
addedge(5, 6, 2);
addedge(6, 7, 17);
addedge(1, 7, 32);
Dijkstra(7, 1);
cout << "以V1为起点,到各点的最短路径:" << endl;
for (int i = 1; i <= 7; i++)
cout << 'V' << i << "\t";
cout << endl;
for (int i = 1; i <= 7; i++)
printf("%2d\t", dist[i]);
}
测试例子:
测试结果:
例题
class Solution {
public:
double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start, int end) {
vector<bool> vi(n, false);//访问数组
vector<vector<pair<double, int>>> path(n, vector<pair<double, int>>());
for (int i = 0; i < edges.size(); i++) {//邻接表
auto& e = edges[i];
path[e[0]].push_back({ succProb[i], e[1] });
path[e[1]].push_back({ succProb[i], e[0] });
}
priority_queue<pair<double, int>> pq;//默认最大堆,根据pair中首个元素double排序
pq.push({ 1.0, start }); //首元素,概率设置为1
while (!pq.empty()) {
auto [curProb, cur] = pq.top();//这种写法仅支持c++17之后
pq.pop();
if (vi[cur]) continue;
vi[cur] = true;
if (cur == end) return curProb;
for (auto[nextProb, next] : path[cur]) {//对相邻节点 bfs
if (vi[next]) continue;
pq.push({ curProb * nextProb, next });
}
}
return 0;
}
};