问题 D: 最短路径

时间限制: 1 Sec  内存限制: 32 MB
提交: 187  解决: 34
 

题目描述

有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

经验总结

我只想说。。。。这题真是出了鬼了,同样的思想,邻接表可以通过,邻接矩阵却怎么都无法通过,说起来邻接表确实和邻接矩阵不同,邻接表中的存放的都是可达边,而邻接矩阵是用最大整数来近似代表两点之间不可达,这里可能就会出一些问题。。。
但是,,,我确实木有试出来到底怎样邻接矩阵才可以通过测试(表示很无奈- -||),评论区已有大佬试了出来。。就是输入数据的两个顶点之间竟然有多条边,详情请见评论区大佬的代码_(:з」∠)_
用邻接表实现就是中规中矩的迪杰斯特拉就可以了,关于题中所说有多条最短路径时输出字典序最小的那一条,先用容器数组存储多条路经,然后再利用DFS进行比较~~感谢评论区的童鞋指正,原来的比较顺序错了,现在已经更正过来了~~

正确代码

#include <cstdio>
#include <vector>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
bool vis[maxn];
int n,d[maxn],G[maxn][maxn];
vector<int> pre[maxn],temppath,path;
struct node
{
int v,w;
node(int x,int y):v(x),w(y){ };
};
vector<node> adj[maxn];
void Dijkstra(int s)
{
fill(d,d+maxn,INF);
fill(vis,vis+maxn,false);
d[s]=0;
for(int i=1;i<=n;++i)
{
int min=INF,u=-1;
for(int j=1;j<=n;++j)
{
if(d[j]<min&&vis[j]==false)
{
u=j;
min=d[j];
}
}
if(u==-1)
return ;
vis[u]=true;
for(int j=0;j<adj[u].size();++j)
{
int v=adj[u][j].v;
if(vis[v]==false)
{
if(d[u]+adj[u][j].w<d[v])
{
d[v]=d[u]+adj[u][j].w;
pre[v].clear();
pre[v].push_back(u);
}
else if(d[u]+adj[u][j].w==d[v])
{
pre[v].push_back(u);
}
}
}
}
}
bool compare(vector<int> a,vector<int> b)
{
int i=a.size()-1,j=b.size()-1;
while(i>=0&&j>=0)
{
if(a[i]!=b[j])
return a[i]<b[j];
--i;--j;
}
return a.size()<b.size();
}

void DFS(int v,int s)
{
if(v==s)
{
temppath.push_back(v);
if(path.size()==0)
path=temppath;
else if(compare(temppath,path))
path=temppath;
temppath.pop_back();
return ;
}
temppath.push_back(v);
for(int i=0;i<pre[v].size();++i)
DFS(pre[v][i],s);
temppath.pop_back();
}
int main()
{
int m,s,t,d1,d2,w;
while(~scanf("%d %d %d %d",&n,&m,&s,&t))
{
for (int i=1;i<=n;++i)
adj[i].clear();
for(int i=0;i<m;++i)
{
scanf("%d %d %d",&d1,&d2,&w);
adj[d1].push_back(node(d2,w));
adj[d2].push_back(node(d1,w));
}
Dijkstra(s);
if(d[t]==INF)
{
printf("can't arrive\n");
}
else
{
printf("%d\n",d[t]);
temppath.clear();
path.clear();
DFS(t,s);
for(int i=path.size()-1;i>=0;--i)
printf("%d%c",path[i],i>0?' ':'\n');
}
}
return 0;
}