《算法笔记》10.4小节——图算法专题->最短路径 问题 D: 最短路径
题目描述
有n个城市m条道路(n<1000, m<10000),每条道路有个长度,请找到从起点s到终点t的最短距离和经过的城市名。
输入
输入包含多组测试数据。
每组第一行输入四个数,分别为n,m,s,t。
接下来m行,每行三个数,分别为两个城市名和距离。
输出
每组输出占两行。
第一行输出起点到终点的最短距离。
第二行输出最短路径上经过的城市名,如果有多条最短路径,输出字典序最小的那条。若不存在从起点到终点的路径,则输出“can't arrive”。
样例输入
3 3 1 3
1 3 3
1 2 1
2 3 1
样例输出
2
1 2 3
分析:《算法笔记》上的 dijkstra + DFS 模板题。注意这道题给出的数据里,两点之间有多条边, 之后输入的边会覆盖前面的,每次读入边的时候要比较是否是最短的边。如果用邻接表,因为会把每条边都存,就不会有覆盖的情况。
#include<algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <queue>
#include <stack>
#include <ctime>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3fffffff
#define db1(x) cout<<#x<<"="<<(x)<<endl
#define db2(x,y) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<endl
#define db3(x,y,z) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<endl
#define db4(x,y,z,r) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<endl
#define db5(x,y,z,r,w) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<", "<<#w<<"="<<(w)<<endl
using namespace std;int graph[1001][1001];void dijkstra(int n,int s,int t,int d[],vector<int>pre[])
{bool vis[n+5]={0};d[s]=0;for(int times=0;times<n;++times){int u=-1,mini=INF;for(int i=0;i<=n;++i){if(!vis[i]&&d[i]<mini)u=i,mini=d[i];}if(u==-1)return;vis[u]=1;for(int i=0;i<=n;++i){if(!vis[i]&&graph[u][i]!=INF){if(d[i]>d[u]+graph[u][i]){d[i]=d[u]+graph[u][i];pre[i].clear();pre[i].push_back(u);}else if(d[i]==d[u]+graph[u][i]){pre[i].push_back(u);}}}}
}
//用一个vector存储路径经过的点序列,保留字典序最小的
void dfs(vector<int>pre[],int s,int t,vector<int>&ans,vector<int>temp)
{temp.push_back(t);if(t==s){vector<int>rev;for(int i=temp.size()-1;i>=0;--i){rev.push_back(temp[i]);}if(ans.empty()||rev<ans)ans=rev;return;}for(int i=0;i<pre[t].size();++i){dfs(pre,s,pre[t][i],ans,temp);}
}int main(void)
{#ifdef testfreopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);clock_t start=clock();#endif //testint n,m,s,t;while(~scanf("%d%d%d%d",&n,&m,&s,&t)){int d[n+5]={0};vector<int>pre[n+5];for(int i=0;i<=n;++i){d[i]=INF;for(int j=0;j<=n;++j)graph[i][j]=INF;}for(int i=0;i<m;++i){int a,b,c;scanf("%d%d%d",&a,&b,&c);if(graph[a][b]>c)graph[a][b]=graph[b][a]=c;}dijkstra(n,s,t,d,pre);if(d[t]==INF)printf("can't arrive\n");else{printf("%d\n",d[t]);vector<int>ans,temp;dfs(pre,s,t,ans,temp);for(int i=0;i<ans.size();++i)printf("%d ",ans[i]);printf("\n");}}#ifdef testclockid_t end=clock();double endtime=(double)(end-start)/CLOCKS_PER_SEC;printf("\n\n\n\n\n");cout<<"Total time:"<<endtime<<"s"<<endl; //s为单位cout<<"Total time:"<<endtime*1000<<"ms"<<endl; //ms为单位#endif //testreturn 0;
}