Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 32824   Accepted: 11098

Description

Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible.

Farmer John's field has N (2 <= N <= 1000) landmarks in it, uniquely numbered 1..N. Landmark 1 is the barn; the apple tree grove in which Bessie stands all day is landmark N. Cows travel in the field using T (1 <= T <= 2000) bidirectional cow-trails of various lengths between the landmarks. Bessie is not confident of her navigation ability, so she always stays on a trail from its start to its end once she starts it.

Given the trails between the landmarks, determine the minimum distance Bessie must walk to get back to the barn. It is guaranteed that some such route exists.

Input

* Line 1: Two integers: T and N

* Lines 2..T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the trail travels. The third integer is the length of the trail, range 1..100.

Output

* Line 1: A single integer, the minimum distance that Bessie must travel to get from landmark N to landmark 1.

Sample Input

  1. 5 5
  2. 1 2 20
  3. 2 3 30
  4. 3 4 20
  5. 4 5 20
  6. 1 5 100

Sample Output

  1. 90

Hint

INPUT DETAILS:

There are five landmarks.

OUTPUT DETAILS:

Bessie can get home by following trails 4, 3, 2, and 1.

 

Dijkstra算法

1.定义概览

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)

2.算法描述

1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

2)算法步骤:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。

执行动画过程如下图

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. using namespace std;
  5.  
  6. const int INF=; //设为无穷大
  7. int maps[][],v[],d[]; //v表示是否已经过遍历 d表示从源到点当前最短路
  8. int n;
  9.  
  10. void Dijkstra(int s,int t)
  11. {
  12. int i,j,k,mini;
  13. for(i=;i<=n;i++)
  14. d[i]=INF; //除源点设为0距离外 其他先设为无穷大
  15. d[s]=;
  16. for(i=;i<=n;i++) //n点循环n次
  17. {
  18. mini=INF;
  19. k=-;
  20. for(j=;j<=n;j++) //在所有未标记点中 选d值最小的点
  21. {
  22. if(!v[j] && d[j]<mini)
  23. {
  24. mini=d[k=j];
  25. }
  26. }
  27. v[k]=; //标记节点
  28. if(k==t)
  29. {
  30. printf("%d\n",d[t]);
  31. return;
  32. }
  33. for(j=;j<=n;j++)
  34. {
  35. if(!v[j] && d[k]+maps[k][j]<d[j]) //表示从k出发的点,对于所有边,更新相连点
  36. {
  37. d[j]=d[k]+maps[k][j];
  38. }
  39. }
  40. }
  41. }
  42.  
  43. int main()
  44. {
  45. int T,i,j,x,y,D;
  46. while(scanf("%d %d",&T,&n)!=EOF)
  47. {
  48. memset(v,,sizeof(v)); //清除标记
  49. for(i=;i<=n;i++)
  50. {
  51. for(j=;j<=n;j++)
  52. {
  53. maps[i][j]=INF;
  54. }
  55. }
  56. for(i=;i<=T;i++)
  57. {
  58. scanf("%d %d %d",&x,&y,&D);
  59. if(maps[x][y]>D) //可能有多条路,只记录最短的
  60. maps[x][y]=D,maps[y][x]=D;
  61. }
  62. Dijkstra(,n);
  63. }
  64. return ;
  65. } //END Thankyou

spfa

是一种求单源最短路的算法

算法中需要用到的主要变量

int n;  //表示n个点,从1到n标号

int s,t;  //s为源点,t为终点

int d[N];  //d[i]表示源点s到点i的最短路

int p[N];  //记录路径(或者说记录前驱)

queue <int> q;  //一个队列,用STL实现,当然可有手打队列,无所谓

bool vis[N];   //vis[i]=1表示点i在队列中 vis[i]=0表示不在队列中

 

几乎所有的最短路算法其步骤都可以分为两步

1.初始化

2.松弛操作

 

初始化: d数组全部赋值为INF(无穷大);p数组全部赋值为s(即源点),或者赋值为-1,表示还没有知道前驱

             然后d[s]=0;  表示源点不用求最短路径,或者说最短路就是0。将源点入队;

    (另外记住在整个算法中有顶点入队了要记得标记vis数组,有顶点出队了记得消除那个标记)

队列+松弛操作

读取队头顶点u,并将队头顶点u出队(记得消除标记);将与点u相连的所有点v进行松弛操作,如果能更新估计值(即令d[v]变小),那么就更新,另外,如果点v没有在队列中,那么要将点v入队(记得标记),如果已经在队列中了,那么就不用入队

以此循环,直到队空为止就完成了单源最短路的求解

 

SPFA可以处理负权边

定理: 只要最短路径存在,上述SPFA算法必定能求出最小值。

证明:

  每次将点放入队尾,都是经过松弛操作达到的。换言之,每次的优化将会有某个点v的最短路径估计值d[v]变小。所以算法的执行会使d越来越小。由于我们假定图中不存在负权回路,所以每个结点都有最短路径值。因此,算法不会无限执行下去,随着d值的逐渐变小,直到到达最短路径值时,算法结束,这时的最短路径估计值就是对应结点的最短路径值。(证毕)

期望的时间复杂度O(ke), 其中k为所有顶点进队的平均次数,可以证明k一般小于等于2。

判断有无负环:

  如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)

  1. int spfa_bfs(int s)
  2. {
  3. queue <int> q;
  4. memset(d,0x3f,sizeof(d));
  5. d[s]=;
  6. memset(c,,sizeof(c));
  7. memset(vis,,sizeof(vis));
  8.  
  9. q.push(s); vis[s]=; c[s]=;
  10. //顶点入队vis要做标记,另外要统计顶点的入队次数
  11. int OK=;
  12. while(!q.empty())
  13. {
  14. int x;
  15. x=q.front(); q.pop(); vis[x]=;
  16. //队头元素出队,并且消除标记
  17. for(int k=f[x]; k!=; k=nnext[k]) //遍历顶点x的邻接表
  18. {
  19. int y=v[k];
  20. if( d[x]+w[k] < d[y])
  21. {
  22. d[y]=d[x]+w[k]; //松弛
  23. if(!vis[y]) //顶点y不在队内
  24. {
  25. vis[y]=; //标记
  26. c[y]++; //统计次数
  27. q.push(y); //入队
  28. if(c[y]>NN) //超过入队次数上限,说明有负环
  29. return OK=;
  30. }
  31. }
  32. }
  33. }
  34.  
  35. return OK;
  36.  
  37. }

 

Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))的更多相关文章

  1. Dijkstra算法——单源最短路径问题

    学习一个点到其余各个顶点的最短路径--单源最短路径 Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向 ...

  2. Dijkstra算法——单源最短路算法

    一.介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他各个节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 适用于有 ...

  3. Dijkstra求解单源最短路径

    Dijkstra(迪杰斯特拉)单源最短路径算法 Dijkstra思想 Dijkstra是一种求单源最短路径的算法. Dijkstra仅仅适用于非负权图,但是时间复杂度十分优秀. Dijkstra算法主 ...

  4. hdu 2680 最短路径(dijkstra算法+多源最短路径单源化求最小值)这题有点意思

    Choose the best route Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  5. POJ 2387 Til the Cows Come Home(模板——Dijkstra算法)

    题目连接: http://poj.org/problem?id=2387 Description Bessie is out in the field and wants to get back to ...

  6. kuangbin专题专题四 Til the Cows Come Home POJ - 2387

    题目链接:https://vjudge.net/problem/POJ-2387 题意:从编号为n的城市到编号为1的城市的最短路. 思路:dijkstra模板题,直接套板子,代码中我会带点注释给初学者 ...

  7. (最短路 弗洛伊德) Til the Cows Come Home -- POJ --2387

      #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> ...

  8. 单源最短路径Dijkstra算法,多源最短路径Floyd算法

    1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...

  9. 单源最短路径——dijkstra算法

    dijkstra算法与prim算法的区别   1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...

随机推荐

  1. [javascript] ajaxfileupload.js 跨域上传文件

    原文地址: http://www.ueffort.com/jqueryajaxfileupload-js-duo-wen-jian-shang-chuan-chuan-zhi-kua-yu/ 跨域 这 ...

  2. [php] PHPExcel插入图片

    其它的代码就不贴了,直接上关键代码: $objPHPExcel = new PHPExcel(); $objPHPExcel->setActiveSheetIndex(0); $objActSh ...

  3. android 项目学习随笔三(Fragment )

    1.在主页面(activity引用Fragment )的布局文件中定义FrameLayout ,加载Fragment  <FrameLayout xmlns:android="http ...

  4. redis 笔记06 发布与订阅、事务、慢查询日志、监视器

    发布与订阅 1. 服务器状态在pubsub_channels字典保存了所有频道的订阅关系:SUBSCRIBE命令负责将客户端和被订阅的频道关联到这个字典里面,而UNSUBSCRIBE命令则负责 解除客 ...

  5. linux设备驱动归纳总结(四):2.进程调度的相关概念【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-65555.html linux设备驱动归纳总结(四):2.进程调度的相关概念 xxxxxxxxxxxx ...

  6. JSP中文乱码问题解决方法小结

    在使用JSP的过程中,最使人头疼的一个问题就是中文乱码问题,以下是我在软件开发中遇到的乱 码问题以及解决方法. 1.JSP页面乱码 这种乱码的原因是应为没有在页面里指定使用的字符集编码,解决方法:只要 ...

  7. android 之 Crash信息的持久化处理

    需求: 持久化运行时异常的信息 1.CrashHandler.java import android.content.Context; import android.content.pm.Packag ...

  8. memcache缓存的使用

    今天在,本地测试了一个关于memcache的demo. 本地集成环境(wamp)环境如下:php 5.5.12  .Apache 2.4.9 .mysql 5.6.17 1.除了添加配置.添加php的 ...

  9. JavaScript DOM 编程艺术(第2版)读书笔记(6)

    案例研究:图片库改进版 我们在学校里学过一种理论,叫做结构化程序设计.其中有这样一条原则:函数应该只有一个入口和一个出口.从理论上讲,我很赞同这项原则:但在实际工作中,过分拘泥于这项原则往往会使代码变 ...

  10. ubuntu12.04下安卓编译环境搭建总结

    前言:      因为工作需要,经常要编译安卓下的动态库,公司有已经搭建好环境的服务器,但是第一自己想自己搭建一下了解一个整个过程,另外,公司的服务器也经常出现问 题,导致编译不了,所以就想自己搭建环 ...