问题 D: 最短路径
题目描述
有n个城市m条道路(n<1000, m<10000),每条道路有个长度,请找到从起点s到终点t的最短距离和经过的城市名。
输入
输入包含多组测试数据。
每组第一行输入四个数,分别为n,m,s,t。
接下来m行,每行三个数,分别为两个城市名和距离。
输出
每组输出占两行。
第一行输出起点到终点的最短距离。
第二行输出最短路径上经过的城市名,如果有多条最短路径,输出字典序最小的那条。若不存在从起点到终点的路径,则输出“can't arrive”。
样例输入 Copy
3 3 1 3 1 3 3 1 2 1 2 3 1
样例输出 Copy
2 1 2 3
代码:
#include <bits/stdc++.h>
using namespace std;
const int INF = (1)<<31-1;
const int maxn = 1010;
struct node{
int v, w;
node(int x, int y):v(x), w(y){};
};
int n, m, s, t;
int dist[maxn];
vector<node> Adju[maxn];
int pre[maxn];
bool visit[maxn] = {false};
vector<int> path, tempPath;
void DIJ(int s){
fill(dist, dist+maxn, INF);
fill(visit, visit+maxn, false);
for(int i=1; i<=n; i++){
pre[i] = i;
}
dist[s] = 0;
for(int i=1; i<=n; i++){
int u = -1, minx = INF;
for(int j=1; j<=n; j++){
if(visit[j]==false&&dist[j]<minx){
u = j;
minx = dist[j];
}
}
if(u==-1) return;
visit[u] = true;
for(int v=1; v<=n; v++){
if(visit[v]==false){
if(dist[u]+Adju[u][v].w<dist[v]){
dist[v] = dist[u]+Adju[u][v].w;
pre[v] = u;
}
else if(dist[u]+Adju[u][v].w==dist[v]&&u<pre[v]){
pre[v] = u;
}
}
}
}
}
void DFS(int v, int s){
if(v==s){
printf("%d ", v);
return;
}
DFS(pre[v], s);
printf("%d ", v);
}
int main(){
while(scanf("%d%d%d%d", &n, &m, &s, &t)!=EOF){
for(int i=1; i<=n; i++){
Adju[i].clear();
}
for(int i=0; i<m; i++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
Adju[u].push_back(node(v, w));
Adju[v].push_back(node(u, w));
}
DIJ(s);
if(dist[t]==INF)
printf("can't arrive\n");
else{
printf("%d\n", dist[t]);
DFS(t, s);
printf("\n");
}
}
return 0;
}