#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f; //无穷大
const int MAXN = 1000010; //最大的点数目
struct qNode {
int v; //起点到达的另一个点
int c; //边的权值
qNode(int _v = 0, int _c = 0) : v(_v), c(_c) {} //构造
bool operator < (const qNode node) const { //优先队列的小于重载
return c > node.c;
}
};
struct Edge { //邻接表内的元素
int v; //与之相邻的另一个顶点
int cost; //该店到达那个顶点的距离
Edge(int _v = 0, int _cost = 0) : v(_v), cost(_cost) {} //构造
};
vector<Edge>E[MAXN]; //邻接表
bool vis[MAXN]; //标记该点是否访问过
int dist[MAXN]; //最短路
priority_queue<qNode>que;
void Dijkstra(int start) { //start为起点
memset(vis, false, sizeof(vis)); //初始化vis数组
memset(dist, INF, sizeof(dist)); //初始化dist数组
while (!que.empty()) { //清空队列
que.pop();
}
dist[start] = 0; //起点到自己的距离为0
que.push(qNode(start, 0)); //把节点压入队列(后面的bfs用到)
qNode tmp;
while (!que.empty()) { //每次取出队首的元素(由于是优先队列,第一个的权值是最小的)
tmp = que.top();
que.pop();
int u = tmp.v; //到达的点
if (vis[u]) continue; //如果访问了就继续取元素
vis[u] = true; //标记该点
for (int i = 0; i < E[u].size(); i++) { //遍历与u点相邻的所有点
int v = E[u][i].v; //u点所能到达的点
int cost = E[u][i].cost; //u点到达该点的花费
if (!vis[v] && dist[v] > dist[u] + cost) { //(松弛)如果没有被访问并且 直接到v的距离 比 先到u再到v 要远一些
dist[v] = dist[u] + cost;
que.push(qNode(v, dist[v])); //并且把该点加入队列(便于找与该点相邻的边)
}
}
}
}
void addEdge(int u, int v, int w) { //加边函数
E[u].push_back(Edge(v, w));
}
int main()
{
int u, v, w; //从u到v的距离为w
int st; //起点
int n, m; //点数和边数
cin >> n >> m;
for (int i = 0; i < m; i++) {
cin >> u >> v >> w;
addEdge(u, v, w);
}
cin >> st;
Dijkstra(st);
for (int i = 1; i <= n; i++)
cout << dist[i] << endl;
return 0;
}
Dijkstra(邻接表+优先队列+堆优化)
最新推荐文章于 2023-06-09 10:46:06 发布