题目描述
有向图负权的单源点最短路问题
输入格式
第1行:2个空格分开的整数n(2<=n<=500)和m(10<=m<=20000),分别表示图的顶点数和边数。
第2..m+1行:每行3个空格分开的整数i,j, w。i表示一条边的起点,j表示终点, w表示权值。
第m+2行:2个整数s,t(1<=s,t<=n),表示指定的顶点。
输出格式
第1行:最小距离
第2行:最短路径(从起点到终点的序列,用1个空格分开)
如果出现负权回路,输出:No Solution
样例
样例输入 1
复制6 7
1 2 2
1 3 -1
2 4 -3
3 4 3
3 6 7
4 6 -2
3 5 6
1 6
样例输出 1
复制-3
1 2 4 6
样例输入 2
复制3 3
1 2 -7
2 3 4
3 1 2
1 3
样例输出 2
复制No Solution
数据范围与提示
无重边。 如果最短路径有多条,输出路径经过边数较小的解; 如果最短路径边数相同,输出编号较小的序列.
_____________________________________________________________________________
写作不易,点个赞呗!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
_____________________________________________________________________________
#include<bits/stdc++.h>
#define PII pair<int,int>
using namespace std;
struct node{
int x;
int y;
int w;
}a[1000005];
int dist[1000005];
int pre[1000005];
int len[1000005];
int n,m,q,p;
bool flag;
int f(){
memset(dist,0x3f3f3f3f,sizeof(dist));
dist[q]=0;
for(int i=1;i<=n-1;i++){
for(int j=1;j<=m;j++){
if(dist[a[j].y]>dist[a[j].x]+a[j].w){
len[a[j].y]=len[a[j].x]+1;
dist[a[j].y]=dist[a[j].x]+a[j].w;
pre[a[j].y]=a[j].x;
}else if(dist[a[j].y]==dist[a[j].x]+a[j].w){
if(len[a[j].y]>len[a[j].x]+1)pre[a[j].y]=a[j].x;
else if(len[a[j].y]==len[a[j].x]+1){
pre[a[j].y]=min(a[j].x,pre[a[j].y]);
}
}
}
}
for(int j=1;j<=m;j++){
if(dist[a[j].y]>dist[a[j].x]+a[j].w){
flag=true;
}
}
return dist[p];
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i].x>>a[i].y>>a[i].w;
}
cin>>q>>p;
int t=f();
if(flag||t==0x3f3f3f3f){
cout<<"No Solution";
return 0;
}
else cout<<t<<endl;
stack<int> sta;
while(p!=0){
sta.push(p);
p=pre[p];
}
while(!sta.empty()){
cout<<sta.top()<<" ";
sta.pop();
}
return 0;
}