#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define P pair<int,int> //pair是一个模板类,含有两个成员数据,
const int maxn = 5e5+5;
struct tree
{
int to, w;
};
vector<tree>a[maxn];
int dis[maxn]; //dis代表最短的距离priority_queue
int n, m, s;
bool b[maxn]; //判断某点是否被遍历过
priority_queue<P, vector<P>, greater<P> > Q; //优先队列是尖括号,升序是greater<P>;最后一个有一格空格
void dijkstra()
{
dis[s] = 0; //优先队列的格式是<类型,储存容器,储存方式 >
Q.push(P(0, s)); //队列的储存格式是Q.push(P(first,second));第一个是"下一个点的"最短路,第二个是"下一个点",
b[0] = true; // "下一个点"相对于该次循环的
while (!Q.empty()) //为空就返回值为真,非空返回值就为假
{
P p = Q.top(); Q.pop(); //Q.top()为取出最顶端元素,因为存储方式为greater,即取出最小值,Q.pop(),是删除最顶端元素以免进入下一次循环
int v = p.second;
if(b[v])
continue;
b[v] = true;
for (int i = 0; i < a[v].size(); i++)
{
int u = a[v][i].to;
if (dis[v] + a[v][i].w < dis[u])
dis[u] = dis[v] + a[v][i].w; //如果到下一个点u的前一个点v的距离加上到下一个点的权值的距离小于到u的距离的话就更新到u的最短距离
if(!b[u]) //如果u没有被存入过,就存入u点信息,以免重复遍历u点
Q.push(P(dis[u], u)); //存入到u的最短路和u方便下一个循环计算
}
}
}
int main()
{
scanf("%d %d %d", &n, &m, &s);
for (int i = 0; i < m; i++)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
a[u].push_back({ v,w });
}
memset(dis, 0x3f, sizeof(dis));
memset(b, 0, sizeof(b));
dijkstra();
for (int i = 1; i < n; i++)
printf("%d ", dis[i]);
printf("%d\n", dis[n]);
return 0;
}
2021/7/27更新
ps:对于dijkstra我选择是用vector 来存边和权值,然后是选择使用优先队列来优化的,但是因为优先队列默认是大根堆,就是大的在前面,所以我选择了greater使用小根堆,然后最开始第一个存的是点,第二个存的是距离,我确实是个逆天了。
看了好一会儿才想起来,优先队列的排序是优先排第一个数,然后如果第一个相同再排第二个,因为我距离是在第二个的,所以,我最开始出来的点不一定是距离最小的点,而一定是序号最小的点,确实是个逆天了。
新的代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define std std::ios::sync_with_stdio(0)
#define mem(a,b) memset(a,b,sizeof(a));
#define P pair<int,int>
const int INF = 0x3f3f3f3f-1;
const int inf = 2147483647;
const int maxn = 5e5 + 10;
struct edge
{
int to, w;
};
vector<edge>a[maxn]; //这里是需要开一个一维的vector
int n, m, s;
int vis[maxn];
ll dis[maxn];
void dijkstra()
{
priority_queue<P, vector<P>, greater<P> >q;
q.push({ 0,s }); //经典pair第一个存的是距离第二个存的是点
dis[s] = 0;
while (!q.empty())
{
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = 1;
for (int i = 0; i < a[u].size(); i++)
{
int v = a[u][i].to;
if (dis[u] + a[u][i].w < dis[v])
{
dis[v] = dis[u] + a[u][i].w;
}
if(!vis[v])
q.push({ dis[v],v });
}
}
}
int main()
{
std;
cin >> n >> m >> s;
for (int i = 0; i < m; i++)
{
int u, v, w;
cin >> u >> v >> w;
a[u].push_back({ v,w });
}
mem(vis, 0);
for (int i = 0; i <= n; i++)
dis[i] = inf;
dijkstra();
for (int i = 1; i <n; i++)
cout << dis[i] << " ";
cout << dis[n] << '\n';
return 0;
}
感觉过了没有一个月,码风变化还是挺大的,哈哈哈