acwing851spfa求最短路,spfa(模板)
由bellman算法,
for (i:1~n) //若1~k则表示最多走k条边的最短路径 for 遍历所以边(a->b,距离c) b的最短路=min(原b的最短路,原a的最短路+a->b的距离)
所以有了优化的SPFA算法————时间复杂度一般o(m),最坏o(nm)
(题目一般保证无负圈)(伪代码):
队列q,st[]记录点是不是在队列里(优化,不优更慢点),cnt[]记录到该点经过几条边——经过n条边即经过n+1个点,说明有负圈
初始化距离dist
起点->q;
while (非空){
top=队头;
pop();
记录top不在队列;
for 遍历top的所以邻点
如果邻点最短路可以比原来小
dist[邻点]更新
cnt[邻点]=cnt[top]+1
if (cnt[邻点]>=n) return;有负圈
if (邻点不在队列里){
邻点->q
记录邻点在队列
}
} 代码(一般无负圈): #include <bits/stdc++.h>
using namespace std;
const int N=100005;
int e[N],ne[N],h[N],w[N],idx;
int n,m,a,b,c;
bool st[N];
int dist[N],cnt[N];
void spfa(){
memset(dist,0x3f,sizeof dist);
dist[1]=0;//!!!!!!!!!!!!
queue<int> q;
q.push(1);
st[1]=true;
while(q.size()){
int top=q.front();
q.pop();
st[top]=false;//!!!!!!!!!!
for(int i=h[top];i!=-1;i=ne[i]){
int pt=e[i];
if(dist[pt]>dist[top]+w[i]){
dist[pt]=dist[top]+w[i];//只要更小就记录下,不能放if st里,因为可能会有两个更新,而后一更新的可能因为st而不执行
cnt[pt]=cnt[top]+1;
if(cnt[pt]>=n) return ;
if(!st[pt]){
q.push(pt);
st[pt]=true;
}
}
}
}
}
int main() {
cin>>n>>m;
memset(h,-1,sizeof(h));
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
e[idx]=b, ne[idx]=h[a], w[idx]=c, h[a]=idx++;
}
spfa();
if(dist[n]>0x3f3f3f3f/2) puts("impossible");
else cout<<dist[n]<<endl;
return 0;
}
注*:不存在最短路有两种情况 第一,1和n之间没有路线
第二,1到n的路上有负圈

快手公司福利 1244人发布