题目链接:
https://begin.lydsy.com/JudgeOnline/problem.php?cid=1318&pid=10
同样的题哈,不一样的解法,也总算是学了Dijkstra了。
[送上一句迟到的祝福:新春快乐]
Problem K: 最短路径问题
Time Limit: 1 Sec Memory Limit: 128 MB
Description
平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现在的任务是找出从一点到另一点之间的最短路径。
Input
共n+m+3行,其中:
第一行为整数n。
第2行到第n+1行(共n行),每行两个整数x和y,描述了一个点的坐标。
第n+2行为一个整数m,表示图中连线的个数。
此后的m行,每行描述一条连线,由两个整数i和j组成,表示第i个点和第j个点之间有连线。
最后一行:两个整数s和t,分别表示源点和目标点。
Output
仅一行,一个实数(保留两位小数),表示从s到t的最短路径长度。
Sample Input
5
0 0
2 0
2 2
0 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5
Sample Output
3.41
HINT
1.题目分析
略 [若还不了解此模板题,请去吐槽本蒟蒻博客最短路(Floyed-Warshall)]
好了,进入正题:
1. 首先了解一下Dijkstra:
Dijkstra算法 O(N2)
用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法,也就是说,只能计算起点只有一个的情况。[书上原话]
同样不能处理负边权。
2. 算法描述:
设起点为s,dis[v]表示从s到v的最短路径,pre[v]为v的前驱节点,用来输出路径,n为总点个数。
(a)初始化:dis[v]=∞(v≠s,显然到起点距离不可能为∞);dis[s]=0(到起点距离为0);pre[s]=0;(起点没有前驱)
(b)for i=1 to (n or n-1) do
①在没有被访问的点中找一个顶点u使得dis[u]最小;
(PS:因为你的开头不小,后面自然就会大,有点像贪心)
②将u标记为当前已确定最短路径;(这里不能太目光短浅)
③
for v=1 to n do
//这里就是为了避免目光短浅,每个点都枚举,因为当前只有u为已确定最短路径,其它点都可能被u所修改
if (dis[v]>dis[u]+dis[u][v])
{
dis[v]>dis[u]+dis[u][v];
//枚举以u为“中转点”的未确定最短路径的点v
pre[v]=u;
//更新前驱点
}
(c)算法结束,dis[v]为s到v的最短距离,pre[v]为v的前驱点,用来输出路径。
3. 算法分析&实例讲解:
1.我们的Dijkstra也是与Floyed差不多,运用“中转点”的思想,但不同的是,我们把起点s也作为一个特殊的“中转点”,而且我们是一步一步往后推最短路。
显然我们可以知道,从s到t的最短路径上,必先经过一个“中转点”v,那么我们在求出到t的最短路时,必先确定到v的最短路,换句话说:
如果起点到某一点v的最短路要经过v0,那么其“中转点”v0一定是于v确定了的最短路径点。
[是不是很绕,没关系,我们画个样例就清楚了。]
2.实例
