SPFA算法
优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止
//算法判环并输出最短路径,边从0开始,点都可以
struct Edge
{
int from,to,dist;
};
vector<Edge> edges;
vector<int> g[1005];//存储from对应的边的标号
bool inq[1005];//是否在队列中
int d[1005];//源点到各个点的最短路
int pre[1005];//最短路的上一条弧
int cnt[1005];//进队次数
int n,m;//n点的个数,m边的个数
int a,b;//求a到b的最短路径并输出a到b的路径
void init()
{
for(int i=0;i<=n-1;i++)
g[i].clear();
edges.clear();
}
void addedge(int from,int to,int dist)//边从0开始
{
edges.push_back((Edge){from,to,dist});
int num=edges.size();
g[from].push_back(num-1);
}
bool spfa(int s)//若存在负环返回false
{
queue<int> q;
memset(inq,0,sizeof(inq));
memset(cnt,0,sizeof(cnt));
memset(d,0x3f,sizeof(d));
d[s]=0;
inq[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
inq[u]=0;
for(int i=0;i<g[u].size();i++)
{
Edge e=edges[g[u][i]];
if(d[e.to]>d[u]+e.dist)//松弛操作
{
d[e.to]=d[u]+e.dist;
pre[e.to]=g[u][i];
if(!inq[e.to])
{
q.push(e.to);
inq[e.to]=1;
if(++cnt[e.to]>n)//最多松弛n-1次,所有有负环
return false;//有负环
}
}
}
}
return true;
}
void print(int s)//输出源点a到s的最短路径
{
if(s==a)
return ;
print(edges[pre[s]].from);
cout<<edges[pre[s]].from<<" ";
}
int main()
{
cin>>n>>m;
init();
for(int i=0;i<=m-1;i++)
{
int a,b,c;
cin>>a>>b>>c;
addedge(a,b,c);
}
cin>>a>>b;
if(spfa(a))
{
cout<<d[b]<<endl;
print(b);
cout<<b<<endl;
}
else
cout<<-1<<endl;