题解 P3371 【【模板】单源最短路径(弱化版)】
这题正解是
以上瞎扯,不用管。
简单介绍一下
具体实现就是这个亚子:
看到第三幅图的那个箭头了吗?那里是不能加入队列的,因为队列里已经有4号点了,这是
(图片来源与洛谷2019夏令营的课件)
这里再说一下有关
- 上面更新点的最短路的操作称为松弛操作
-
-
接下来是最激动人心的时刻:上代码!!!
#include<bits/stdc++.h>
using namespace std;
int n,m,s;
queue<int>q;//系统自带队列,不懂的看底下
vector<int>g[200005];//同上
vector<int>dis[200005];
bool f[100005];//用于标记是否加入队列
int v[100005];//每个点离起点的最短路径
int main()
{
cin>>n>>m>>s;
for(register int i=1;i<=m;i++)
{
int ff,tt,dd;
cin>>ff>>tt>>dd;
g[ff].push_back(tt);
dis[ff].push_back(dd);//建图
}
for(int i=1;i<=n;++i) v[i]=1e10;//初始化,SPFA的初始化必须是一个很大的值,因为它要处理负权边
v[s]=0;
f[s]=true;
q.push(s);//压入起点
while(!q.empty())//直到队列为空为止
{
int xx=q.front();q.pop();//取出第一个元素并弹出
f[xx]=false;//标记为没有加入队列
for(register int i=0;i<g[xx].size();i++)//该节点延伸出来的点
if(v[g[xx][i]]>v[xx]+dis[xx][i])//松弛操作
{
if(!f[g[xx][i]]) q.push(g[xx][i]),f[g[xx][i]]=true;//加入队列
v[g[xx][i]]=v[xx]+dis[xx][i];//更新
}
}
for(register int i=1;i<=n;i++)
if(v[i]!=1e10) cout<<v[i]<<' ';
else cout<<"2147483647"<<' ';
return 0;
}
附: