SPFA
即用队列处理Bellman-Ford。
效率很高,与BFS很像。但不稳定,题目规模很大,且边的权值为非负数时使用Dijkstra算法更好,不宜使用SPFA。
SPFA链式前向星
2544
代码
#include<bits/stdc++.h>
using namespace std;
#define N 1000010
#define INF 0xfffffff
int n,m,a,b,c,dis[N],pre[N],head[N],Neg[N],cnt;
bool inq[N];
struct edge{
int to,next,w;//下一个结点,下一条边,权值
}e[N];
void init(){
for(int i=0;i<N;++i){
e[i].next=-1;
head[i]=-1;
}
cnt=0;
}
void addedge(int u,int v,int w){//前向星存图
e[cnt].to=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt++;
}
int spfa(int s){
memset(Neg, 0, sizeof(Neg));
Neg[s] = 1;
for(int i=1; i<=n; i++) { dis[i]=INF; inq[i]=false; } //初始化
dis[s] = 0; //起点到自己的距离是0
queue<int> Q;
Q.push(s);
inq[s] = true; //起点进队列
while(!Q.empty()) {
int u = Q.front(); Q.pop(); //队头出队
inq[u] = false;
for(int i=head[u]; ~i; i = e[i].next) {//~i也可以写成 i!=-1
int v = e[i].to, w = e[i].w;
if (dis[u]+w < dis[v]) {//u的第i个邻居v,它借道u,到s更近
dis[v] = dis[u]+w; //更新第i个邻居到s的距离
pre[v] = u; //如果有需要,记录路径
if(!inq[v]) {//v更新状态,但是它不在队列中,把它放进队列
inq[v] = true;
Q.push(v);
Neg[v]++;
if(Neg[v] > n) return 1; //出现负圈
}
}
}
}
printf("%d\n",dis[n]); //从s到n的最短距离
return 0;
}
int main(){
while(scanf("%d%d",&n,&m)&&n*m!=0){
init();
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
spfa(1);
}
return 0;
}