//
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e6+7; // 点
const int M=2e6+7; // 边
int n,m;
int h[N],pos; // h[N] 定位边 // pos e[]下标推进
struct edge{ int y,data,next; }e[M];
void init()
{
pos=0;
for( int i=0;i<N;i++ ) h[i]=-1; // 点init
for( int i=0;i<M;i++ ) e[i].next=-1; // 边init
}
void add( int x,int y,int data )
{
e[pos].y=y;
e[pos].data=data;
e[pos].next=h[x]; // 定位之前边
h[x]=pos++; // 定位当前边
}
int dis[N]; // dis[i]: start to i
bool inq[N]; // inq[i]=true: i在队列中
int ne[N]; // 判断负圈
int dad[N]; // 打印路径
int SPFA( int start ) // 返回1表示出现负圈
{
int i,x,y,data;
memset( dis,0x3f,sizeof( dis ) ); // for...
memset( inq,0,sizeof( inq ) );
memset( ne,0,sizeof( ne ) ); // init
dis[start]=0; // 起点 到自己的距离是0
inq[start]=1; // 起点 在队列中
ne[start]=1; // 起点 入过一次队列
queue<int> q; q.push( start );
while( !q.empty() )
{
x=q.front(); q.pop(); inq[x]=0; // 队头出队
for( i=h[x];~i;i=e[i].next ) // 前向星遍历
{
y=e[i].y;
data=e[i].data;
if( dis[y] > dis[x]+data ) // 直达 > 松弛 直达要更新
{
dis[y]=dis[x]+data;
dad[y]=x;
if( !inq[y] ) // y更新了 且y不在队列里
{
q.push(y); inq[y]=1; ne[y]++;
if( ne[y]>=n ) return 1; // ">" vs ">=" ?
} // use_n
}
}
}
return 0;
}
void out( int x,int y ) // 打印路径
{
if( x==y ) { cout<<x<<" "; return ; }
out( x,dad[y] ); cout<<y<<" ";
}
int main()
{
int start,x,y,data,i;
while( cin>>n>>m>>start )
{
init();
if( n==0 && m==0 ) break;
while( m-- )
{
cin>>x>>y>>data;
add( x,y,data ); // 无向边
add( y,x,data );
}
SPFA( start ); // 计算 起点start 到其他所有点的最短路
for( i=1;i<=n;i++ )
{
cout<<dis[i]<<endl;
cout<<"path:"; out( start,i ); cout<<endl;
}
}
return 0;
}
模板_SPFA_链式前向星
猜你喜欢
转载自blog.csdn.net/qq_63173957/article/details/124727899
今日推荐
周排行