城市路(Dijkstra)
时间限制:1秒 内存限制:128M
题目描述
罗老师被邀请参加一个舞会,是在城市n,而罗老师当前所处的城市为1,附近还有很多城市2~n-1,有些城市之间没有直接相连的路,有些城市之间有直接相连的路,这些路都是双向的,当然也可能有多条。 现在给出直接相邻城市的路长度,罗老师想知道从城市1到城市n,最短多少距离。
输入描述
输入n, m,表示n个城市和m条路; 接下来m行,每行a b c, 表示城市a与城市b有长度为c的路。
输出描述
输出1到n的最短路。如果1到达不了n,就输出-1。
样例
输入
5 5 1 2 20 2 3 30 3 4 20 4 5 20 1 5 100输出
90提示
【数据规模和约定】 1≤n≤2000 1≤m≤10000 0≤c≤10000
分析
这道题是一道经典的最短路径问题,我们可以使用Dijkstra(迪杰斯特拉)算法来做。
先来讲一下Dijkstra算法的基本思想:
以此图为例,求V0到其余各点的最短距离:
首先建立三个数组,分别存储未确定的点(a数组)、已确定的点(b数组)、已算出的最短距离(dist):
a[]={V1,V2,V3,V4,V5};
b[]={V0};
dist[]={0};
然后查看V0可以直接到达的点,有V1、V3、V4;
从中找到距离V0最短的一个,是V4;
将V4加入到b数组中,从a数组中删除,并用dist数组记录;
然后已V4为起点寻找,找到最短的一个,并记录;
以此类推,直到找到所有点到V0的最短距离。
这就是Dijkstra算法的基本思想,了解这个之后,就可以做题了。
AC代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=10050;
const int M=2048;
int n,m;
int head[N],v[2*N],nxt[2*N],w[2*N],idx; //由于是无向图,所以N要为2倍
int dis[M]; //存储距离
bool vis[M]; //存储点是否已被找到最短距离
void add(int x,int y,int z){ //邻接表
v[idx]=y;
w[idx]=z;
nxt[idx]=head[x];
head[x]=idx++;
}
void Dijkstra(int s){ //s是起点
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
for(int i=1;i<n;i++){
int t=-1;
for(int j=1;j<=n;j++){
if(!vis[j]&&(t==-1||dis[t]>dis[j])){
t=j;
}
}
vis[t]=true;
for(int j=head[t];~j;j=nxt[j]){
int e=v[j],l=w[j];
dis[e]=min(dis[e],dis[t]+l);
}
}
if(dis[n]==0x3f3f3f3f){ //n点未被赋值,意味着不可能走到
cout<<-1<<endl;
}
else{
cout<<dis[n]<<endl;
}
}
int main(){
memset(head,-1,sizeof(head));
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c); //无向图,两端都要存
}
Dijkstra(1);
return 0;
}