SPFA(Shortest Path Faster Algorithm)是一种经典的最短路算法。
但因其效率的不稳定而常常处于尴尬的境地。。。(是那个出题人要装怪,不是我的错呀)
这篇博客就是用来记录下其的优化。。。
SLF优化
设要加入的节点是j,队首元素为 i i ,若,则将 j j 插入队首,否则插入队尾;
bool SPFA(int s){
for(int i=1;i<=n;i++)dis[i]=1e9;
q.push_back(s);v[s]=1;dis[s]=0;
while(!q.empty()){
int x=q.front();
q.pop_front();v[x]=0;
for(int l=st[x];l;l=nxt[l])
if(dis[ed[l]]>dis[x]+len[l]){
dis[ed[l]]=dis[x]+len[l];
if(!v[ed[l]]){
if((++cnt[ed[l]])==n)return 1;
if(!q.empty()&&dis[ed[l]]<dis[q.front()])
q.push_front(ed[l]);
else q.push_back(ed[l]);
v[ed[l]]=1;
}
}
}
return 0;
}
负权回路的DFS优化
由于朴素的spfa判负权回路(根据入队次数)的复杂度是的,不够优秀。。
于是一个“崭新”的方法就出现了:用DFS实现spfa,当同一条路径上有两个相同的点时,就可知出现负权回路了。
bool SPFA(int x){
v[x]=1;bool b=0;
for(int l=st[x];l;l=nxt[l])
if(dis[ed[l]]>dis[x]+len[l]){
if(v[ed[l]])return 1;
dis[ed[l]]=dis[x]+len[l];
b|=SPFA(ed[l]);
}
v[x]=0;
return b;
}
···
int main(){
···
for(int i=1;i<=n;i++)dis[i]=1e9;
for(int i=1;i<=n;i++)f|=SPFA(i);
···
}