spfa AcWing 851. spfa求最短路
原题链接
算法标签
最短路 spfa
思路
求最短路算法汇总
该图摘自该视频
spfa算法是对Bellman_ford算法的优化
Bellman_ford算法会遍历所有的边,但是有很多的边遍历了其实没有什么意义,我们只用遍历那些到源点距离变小的点所连接的边即可,只有当一个点的前驱结点更新了,该节点才会得到更新;因此考虑到这一点,我们将创建一个队列每一次加入距离被更新的结点。
该图摘自该题解
代码
#include<bits/stdc++.h>
#define int long long
#define rep(i, a, b) for(int i=a;i<b;++i)
#define Rep(i, a, b) for(int i=a;i>b;--i)
using namespace std;
const int N = 100005;
int h[N], e[N], ne[N], w[N], idx;
int dis[N];
bool st[N];
int n,m;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put(int x) {
if(x<0) putchar('-'),x=-x;
if(x>=10) put(x/10);
putchar(x%10^48);
}
void add(int a, int b, int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
int sp(){
memset(dis, 0x3f, sizeof dis);
dis[1]=0;
queue<int> q;
q.push(1);
st[1]=true;
while(q.size()){
int t=q.front();
q.pop();
// 从队列中取出来之后该节点st被标记为false,代表之后该节点如果发生更新可再次入队
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(dis[j]>dis[t]+w[i]){
dis[j]=dis[t]+w[i];
if(!st[j]){// 当前已经加入队列的结点,无需再次加入队列,即便发生了更新也只用更新数值即可,重复添加降低效率
q.push(j);
st[j]=true;
}
}
}
}
return dis[n];
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
memset(h, -1, sizeof h);
n=read(), m=read();
while(m--){
int x=read(), y=read(), z=read();
add(x, y, z);
}
if(sp()==0x3f3f3f3f){
puts("impossible");
}else{
printf("%lld\n", sp());
}
return 0;
}
原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈