POJ 最短路问题集锦:

Dijkstra算法:

详细介绍: http://hi.baidu.com/iotbill/item/cb5fc1de28a3e63721e250d9

Dijkstra算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。

POJ 2387 Til the Cows Come Home    (problem link adress:http://poj.org/problem?id=2387)

虽然题目不是很好读,但本题是Dijkstra算法的模板式样题!相当于Dijkstra的模板了!

View Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 #define Max 0xfffffff
 6 #define N 1005
 7 int p[N][N],mark[N],f[N];
 8 int t,n;
 9 void Dijkstra()
10 {
11     int i,j,k,min;
12     memset(mark,0,sizeof(mark));
13     for(i=1;i<=n;i++)
14         f[i]=p[1][i];
15     f[1]=0;
16     for(i=1;i<=n;i++)
17     {
18         min=Max;
19         for(j=1;j<=n;j++)
20         {
21             if(!mark[j]&&f[j]<min)
22             {
23                 min=f[j];
24                 k=j;
25             }
26         }
27         if(min==Max) break;
28         mark[k]=1;
29         for(j=1;j<=n;j++)
30         {
31             if(!mark[j]&&f[j]>f[k]+p[k][j])
32                 f[j]=f[k]+p[k][j];
33         }
34     }
35      printf("%d\n",f[n]);
36 }
37 int main()
38 {
39     int i,j;
40     while(scanf("%d%d",&t,&n)!=EOF)
41     {
42         for(i=1;i<=n;i++)
43             for(j=1;j<=n;j++)
44                 p[i][j]=Max;
45             for(j=0;j<t;j++)
46             {
47                 int a,b,len;
48                 scanf("%d%d%d",&a,&b,&len);
49                 if(p[a][b]>len)
50                     p[a][b]=p[b][a]=len;
51             }
52             Dijkstra();
53     }
54     return 0;
55 }

本题中,dijkstra中f【i】保存的是原点到节点i的最短距离。

POJ 2253 Frogger   (problem link adress:http://poj.org/problem?id=2253)

第一次读本题的时候,也感觉似懂非懂,由于刷题的顺序是按照别人已经总结好的刷的,所以已经知道别人用Dijkstra解这道题,接着就把题意强扭到了第一块石头到第二块石头的最短距离,结果第二组数据没有通过于是返回认真读题.

前面的那么多东西需要搞懂什么是蛙跳的范围,(最少等于出现的最长蛙跳长度在一个序列中),下面两句话就很重要了。

The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones.

You are given the coordinates of Freddy's stone, Fiona's stone and all other stones in the lake. Your job is to compute the frog distance between Freddy's and Fiona's stone.

真正的把这两句搞懂,题意就懂了。即让我们求最小的蛙跳范围在所有的可能路径中;

可以从节点1开始遍历,到下一节点(保持两节点间距离最小),直到节点2,在这个过程中记录蛙跳范围。

View Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 using namespace std;
 6 #define N 205
 7 #define max 10000000.0
 8 double p[N][N],f[N];
 9 int mark[N];
10 int n;
11 int flag;
12 double getlen(double xx1,double yy1,double xx2,double yy2)
13 {
14       return sqrt(1.0*(xx1-xx2)*(xx1-xx2)+1.0*(yy1-yy2)*(yy1-yy2));
15 }
16 double Dijkstra()
17 {
18     int i,j,k;
19     double min;
20     double temp=0;
21     memset(mark,0,sizeof(mark));
22     for(i=1;i<=n;i++)
23         f[i]=p[1][i];
24     f[1]=0;//把1设置为原点
25     for(i=1;i<=n;i++)
26     {
27         min=max;
28         for(j=1;j<=n;j++)
29         {
30             if(!mark[j]&&f[j]<min)
31             {
32                 min=f[j];
33                 k=j;
34             }
35         }
36       if(min>temp)//temp记录并保存蛙跳范围
37           temp=min;
38       if(k==2)//如果按每步的最小距离遍历到了节点2,返回蛙跳范围
39           return temp;
40       mark[k]=1;
41       for(j=1;j<=n;j++)
42       {
43           if(!mark[j])
44           {
45               double data=p[k][j];
46               if(data<f[j])
47                   f[j]=data;
48           }
49       }
50
51     }
52
53 }
54 int main()
55 {
56     int i,j;    flag=1;
57     while(scanf("%d",&n)&&n)
58     {
59         double x[N], y[N];
60         memset(x,0,sizeof(x));
61         memset(y,0,sizeof(y));
62         for(i=1;i<=n;i++)
63             for(j=1;j<=n;j++)
64             p[i][j]=max;
65         for(i=1;i<=n;i++)
66             scanf("%lf%lf",&x[i],&y[i]);
67         for(i=1;i<=n;i++)
68         {
69             for(j=1;j<=n;j++)
70             {
71                 if(i==j)  continue;
72                 double dis=getlen(x[i],y[i],x[j],y[j]);
73                 if(p[i][j]>dis)
74                     p[i][j]=p[j][i]=dis;
75             }
76         }
77
78     double w=Dijkstra();
79     printf("Scenario #%d\n",flag++);
80     printf("Frog Distance = %.3lf\n\n",w);
81     }
82     return 0;
83 }

本题中,dijkstra中的f[i]记录的是节点i到与它连接的节点的最短距离。

POJ  1797 Heavy Transport  http://poj.org/problem?id=1797

题目大意:有n个路口,每个路口从1到n标记,每两个路口之间有一个限重,问从1到n,最多可以载多重的物体。

本题和上一题的解法类似。注;本题求最大载重,p[i][j]初始化的时候用0或负数初始化,最后每个样例后面要输出一个空格;

实现过程:从节点1开始遍历,寻找与节点1相连的最大权值边,然后把该节点标记,以该节点为中心,然后更新该节点与周围相连节点的权值,这样重复进行;

View Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 #define MIN -1
 6 #define N 1005
 7 int t;
 8 int flag;
 9 int n,m;
10 int p[N][N],mark[N],f[N];
11 int Dijkstra()
12 {
13     int i,j,k,temp,min;
14     memset(mark,0,sizeof(mark));
15     for(i=1;i<=n;i++)
16         f[i]=p[1][i];
17     f[1]=0;mark[1]=1;
18     temp=1000005;
19     for(i=1;i<=n;i++)
20     {
21         min=-1;
22         for(j=0;j<=n;j++)
23         {
24             if(!mark[j]&&f[j]>min)
25             {
26                 min=f[j];
27                 k=j;
28             }
29
30         }
31         if(temp>min)
32             temp=min;
33         if(k==n)
34             return temp;
35         mark[k]=1;
36         for(j=1;j<=n;j++)
37         {
38             if(!mark[j])
39             {
40                 int w=p[k][j];
41                 if(w>f[j])
42                     f[j]=w;
43             }
44         }
45
46     }
47 }
48 int main()
49 {
50     int i,j;
51     scanf("%d",&t);
52     flag=1;
53     while(t--)
54     {
55         scanf("%d%d",&n,&m);
56         for(i=1;i<=n;i++)
57             for(j=0;j<=n;j++)
58                 p[i][j]=MIN;
59         for(i=1;i<=m;i++)
60         {
61             int a,b,len;
62             scanf("%d%d%d",&a,&b,&len);
63             if(p[a][b]<len)
64                 p[a][b]=p[b][a]=len;
65         }
66         printf("Scenario #%d:\n",flag++);
67         printf("%d\n\n",Dijkstra());
68     }
69     return 0;
70 }

本题中,dijkstra中的f【j】记录的是节点i到与它连接的节点的最长距离。

上述三题可以知道,根据题目的不同,dijkstra可以做出相应的变化来适合题目。其中,处理最短路的问题时可以用f【i】来保存,原点来目标点的最小距离,处理最大或者最小的边权值时可以用f【i】来保存当前节点与下一节点的最短或最长距离,两者的实现都要通过一个循环来不断的松弛实现。

POJ 3268  Silver Cow Party       http://poj.org/problem?id=3268

题意:一群牛(每头牛居住一个的农场,标号从1到n)到第n头牛家里聚会,牛很聪明啊!走的都是最短路,聚会结束,牛各回各家,但是就不能沿着原路返回了,因为是单程的!

问这群牛中谁花费的时间最长?

这样的单向图以前很少做!菜鸟想的简单啊!以为f【i】=p【i】【x】记录的就是 i 牛向x牛奔去最短的距离, b【i】=p【x】【i】记录的就是从x牛的农场各自奔回自己的家中;

于是敲了两次Dijkstra,交上去居然错了!     Google一下原来涉及单向图的时候,反过来的时候还是需要转置的,学习了!

WA  代码:

View Code

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 using namespace std;
  5 #define N 1005
  6 #define max 0xfffffff
  7 int n,m,x;
  8 int f[N],b[N],mark[N],p[N][N];
  9 void Dijkstra_go()
 10 {
 11     int i,j,k,min;
 12     memset(mark,0,sizeof(mark));
 13     for(i=1;i<=n;i++)
 14         f[i]=p[i][x];
 15     f[x]=0;
 16     mark[x]=1;
 17     for(i=1;i<=n;i++)
 18     {
 19         min=max;
 20         for(j=1;j<=n;j++)
 21         {
 22             if(!mark[j]&&f[j]<min)
 23             {
 24                 min=f[j];
 25                 k=j;
 26             }
 27         }
 28         if(min==max) break;
 29         mark[k]=1;
 30         for(j=1;j<=n;j++)
 31         {
 32             if(!mark[j]&&f[j]>f[k]+p[k][j])
 33                 f[j]=f[k]+p[k][j];
 34         }
 35     }
 36 //    for(i=1;i<=n;i++)
 37 //        printf("%d ",f[i]);
 38 //    printf("\n");
 39 }
 40 void Dijkstra_back()
 41 {
 42     int i,j,k,min;
 43     memset(mark,0,sizeof(mark));
 44     for(i=1;i<=n;i++)
 45         b[i]=p[x][i];
 46     b[x]=0;
 47     mark[x]=1;
 48     for(i=1;i<=n;i++)
 49     {
 50         min=max;
 51         for(j=1;j<=n;j++)
 52         {
 53             if(!mark[j]&&b[j]<min)
 54             {
 55                 min=b[j];
 56                 k=j;
 57
 58             }
 59         }
 60         if(min==max)  break;
 61         mark[k]=1;
 62         for(j=1;j<=n;j++)
 63         {
 64             if(!mark[j]&&b[j]>b[k]+p[k][j])
 65                 b[j]=b[k]+p[k][j];
 66
 67         }
 68     }
 69 //    for(i=1;i<=n;i++)
 70 //        printf("%d ",b[i]);
 71 //    printf("\n");
 72 }
 73
 74
 75
 76 int main()
 77 {
 78     int i,j;
 79     while(scanf("%d%d%d",&n,&m,&x)!=EOF)
 80     {
 81         for(i=1;i<=n;i++)
 82             for(j=1;j<=n;j++)
 83                 p[i][j]=max;
 84         for(i=1;i<=m;i++)
 85         {
 86             int a,b,len;
 87             scanf("%d%d%d",&a,&b,&len);
 88             if(p[a][b]>len)
 89                 p[a][b]=len;
 90         }
 91         memset(f,0,sizeof(f));
 92         memset(b,0,sizeof(f));
 93         Dijkstra_go();
 94         Dijkstra_back();
 95         int  ans=-1;
 96         for(i=1;i<=n;i++)
 97         {
 98             f[i]+=b[i];
 99             if(f[i]>ans)
100                 ans=f[i];
101         }
102         printf("%d\n",ans);
103     }
104     return 0;
105 }

参考后修改的AC代码:

View Code

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 using namespace std;
  5 #define N 1005
  6 #define max 0xfffffff
  7 int n,m,x;
  8 int f[N],b[N],mark[N],p1[N][N],p2[N][N];
  9 void Dijkstra_go()
 10 {
 11     int i,j,k,min;
 12     memset(mark,0,sizeof(mark));
 13     for(i=1;i<=n;i++)
 14         f[i]=p1[x][i];
 15     f[x]=0;
 16     mark[x]=1;
 17     for(i=1;i<=n;i++)
 18     {
 19         min=max;
 20         for(j=1;j<=n;j++)
 21         {
 22             if(!mark[j]&&f[j]<min)
 23             {
 24                 min=f[j];
 25                 k=j;
 26             }
 27         }
 28         if(min==max) break;
 29         mark[k]=1;
 30         for(j=1;j<=n;j++)
 31         {
 32             if(!mark[j]&&f[j]>f[k]+p1[k][j])
 33                 f[j]=f[k]+p1[k][j];
 34         }
 35     }
 36 //    for(i=1;i<=n;i++)
 37 //        printf("%d ",f[i]);
 38 //    printf("\n");
 39 }
 40 void Dijkstra_back()
 41 {
 42     int i,j,k,min;
 43     memset(mark,0,sizeof(mark));
 44     for(i=1;i<=n;i++)
 45         b[i]=p2[x][i];
 46     b[x]=0;
 47     mark[x]=1;
 48     for(i=1;i<=n;i++)
 49     {
 50         min=max;
 51         for(j=1;j<=n;j++)
 52         {
 53             if(!mark[j]&&b[j]<min)
 54             {
 55                 min=b[j];
 56                 k=j;
 57
 58             }
 59         }
 60         if(min==max)  break;
 61         mark[k]=1;
 62         for(j=1;j<=n;j++)
 63         {
 64             if(!mark[j]&&b[j]>b[k]+p2[k][j])
 65                 b[j]=b[k]+p2[k][j];
 66
 67         }
 68     }
 69 //    for(i=1;i<=n;i++)
 70 //        printf("%d ",b[i]);
 71 //    printf("\n");
 72 }
 73
 74
 75
 76 int main()
 77 {
 78     int i,j;
 79     while(scanf("%d%d%d",&n,&m,&x)!=EOF)
 80     {
 81         for(i=1;i<=n;i++)
 82             for(j=1;j<=n;j++)
 83             {
 84                 p1[i][j]=max;
 85                 p2[i][j]=max;
 86             }
 87         for(i=1;i<=m;i++)
 88         {
 89             int a,b,len;
 90             scanf("%d%d%d",&a,&b,&len);
 91             if(p1[a][b]>len)
 92             {
 93                 p1[a][b]=len;
 94                 p2[b][a]=len;
 95             }
 96         }
 97         memset(f,0,sizeof(f));
 98         memset(b,0,sizeof(f));
 99         Dijkstra_go();
100         Dijkstra_back();
101         int  ans=-1;
102         for(i=1;i<=n;i++)
103         {
104             f[i]+=b[i];
105             if(f[i]>ans)
106                 ans=f[i];
107         }
108         printf("%d\n",ans);
109     }
110     return 0;
111 }

POJ 1847   Tram   http://poj.org/problem?id=1847

汗!本题居然没读懂!英语太菜了!呵呵。。。四级含金量不高啊!搜了篇文章才弄懂题意。

本题最大的挑战就是读题,题目弄清楚了,就ok了!    Dijkstra的应用!

View Code

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define N 105
 6 #define max 0xfffffff
 7 int f[N],mark[N],p[N][N];
 8 int n,a,b;
 9 void Dijkstra()
10 {
11     int i,j,k,min;
12     memset(mark,0,sizeof(mark));
13     for(i=1;i<=n;i++)
14         f[i]=p[a][i];
15     f[a]=0;
16     mark[a]=1;
17     for(i=1;i<=n;i++)
18     {
19         min=max;
20         for(j=1;j<=n;j++)
21         {
22             if(!mark[j]&&f[j]<min)
23             {
24                 min=f[j];
25                 k=j;
26             }
27         }
28         if(min==max) break;
29         mark[k]=1;
30         for(j=1;j<=n;j++)
31         {
32             if(!mark[j]&&f[k]+p[k][j]<f[j])
33                 f[j]=f[k]+p[k][j];
34         }
35     }
36     if(f[b]==max)   printf("-1\n");
37     else
38         printf("%d\n",f[b]);
39 }
40 int main()
41 {
42     int i,j;
43     while(scanf("%d%d%d",&n,&a,&b)!=EOF)
44     {
45         int c;
46         for(i=1;i<=n;i++)
47             for(j=1;j<=n;j++)
48                 p[i][j]=max;
49         for(i=1;i<=n;i++)
50         {
51             scanf("%d",&c);
52             if(c==0)  continue;//第一次的时候忘了考虑c的取值,所以Time Limit Exceeded了一次
53             int d;
54             scanf("%d",&d);
55             p[i][d]=0;
56             c-=1;
57             while(c--)
58             {
59                 scanf("%d",&d);
60                 p[i][d]=1;
61             }
62         }
63         Dijkstra();
64     }
65     return 0;
66 }

参考网络资料:http://www.cppblog.com/abilitytao/archive/2009/07/07/89459.html

转载于:https://www.cnblogs.com/heat-man/archive/2013/03/18/2966615.html

POJ 最短路问题-Dijkstra相关推荐

  1. poj 2378 (dijkstra)

    http://poj.org/problem?id=2387 一个dijkstra的模板题 #include <stdio.h> #include <string.h> #de ...

  2. poj 1797 Dijkstra算法

    题意: 给定n个顶点,以及m条边,每条边包括:起点,终点,权重 现在要从顶点出发到达顶点n,求路径中能够承受的最大权重 思路: 本题要求出从顶点1到n的所有的可行路径中各边权值的最小值的最大值 max ...

  3. Poj 3255(dijkstra求次短路)

    题目传送门 详情见<挑战程序设计竞赛>P109 代码如下: #include <algorithm> #include <cstdio> #include < ...

  4. 第六天PAT-A1003 Emergency最短路问题Dijkstra算法(小根堆)描述及模板

    A1003 Description: 作为一个城市的急救队领导,你会得到你所在城市的一个特别地图.这张地图展示了一些由一些路径相连的几个零散的城市.每个城市的救援队总数和连接两个城市的道路的长度都标注 ...

  5. 最短路问题 Dijkstra标号法

    http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html http://www.61mon.com/index.php/ar ...

  6. D - Silver Cow Party POJ - 3268

    D - Silver Cow Party POJ - 3268 dijkstra 是 O(n2),堆优化一下, O(nlogn) 对每个点跑一次 dj, 取 max(dis(x->i)+dis( ...

  7. 【最短路算法】dijkstra,SPFA和folyd

    在了解本知识点之前,首先要了解图的建立,也就是邻接表和邻接矩阵. 邻接矩阵适用于稠密图 邻接表适用于稀疏图 目录 单源最短路问题 dijkstra算法 SPFA算法 folyd算法 最小生成树 拓扑排 ...

  8. linux 编译opencv 慢,opencv4.0 cuda10 编译速度太慢

    图论$\cdot$最短路问题 Dijkstra单源最短路径算法 Dijkstra可以计算出发点到每个点的最短路,及单源最短路径(SSSP).这一特点使得Dijkstra常常用来进行其他算法的预处理.用 ...

  9. 人狗鸡米安全过河matlab程序,人狗鸡米过河

    1.学校代码: 10128学 号: 6选修课结业论文(题 目:人狗鸡米过河问题学生姓名:武彩学 院:理学院系 别:数学系专 业:信息与计算科学班 级:信计08-1二 一二 年 5月人狗鸡米过河问题一. ...

最新文章

  1. AJAX ControlToolkit学习日志-ModalPopupExtender(16)
  2. pro调用python libs_使用WingPro 7 设置Python路径的方法
  3. mybatis学习(10): sql server身份验证和windows身份验证
  4. qrcode生产带logo_比亚迪换新标?新Logo的含义你了解吗?
  5. centos mysql mongodb_MySQL与MongoDB
  6. 帮你快速拿Offer!渣本逆袭大厂面经分享
  7. 为什么很多人说Python简单呢?
  8. Nessus高级使用研究
  9. MAC将latex等大软件安装到移动硬盘
  10. 为Springboot工作流版本myabaits的xml 建表
  11. 三、网页中的超链接(hyperlink)
  12. Maven读这一篇就够了
  13. 面试分享:专科半年经验面试阿里前端P6+总结
  14. 【图像分割】基于模糊核聚类算法KFCM实现医学图像分割matlab代码
  15. 吐血分享:QQ群霸屏技术教程之霸屏实施细则
  16. 利用-flat.vmdk文件恢复ESXI虚拟机的vmdk文件
  17. 常微分方程的解法 (四): Matlab 解法
  18. 简单说说rebuttal
  19. 7天玩转阿里云服务器第1天:云服务器ECS是什么
  20. Java各种加密和解密方式

热门文章

  1. 数十个锂电池充放电电路,锂电池充放电芯片
  2. 做网站都需要哪些基本栏目呢?
  3. 现在国内找工作行情不好,分享一些可以base国内的海外远程工作机会
  4. camunda流程引擎概念术语
  5. 生成pdf base64字符串
  6. docker部署jumpserver
  7. 游戏服务器框架升级-无入侵式代理解决方案
  8. 电脑桌面上计算机有地址栏吗,电脑窗口地址栏清理
  9. ARCore Depth API 深度解析:算法原理及开发细节
  10. 安全研究人员推出鱼叉式网络钓鱼黑箱粉碎机