码迷,mamicode.com
首页 > 其他好文 > 详细

最短路总结

时间:2019-10-05 10:26:58      阅读:74      评论:0      收藏:0      [点我收藏+]

标签:void   col   核心   农夫   strong   href   itemid   namespace   php   

Floyd算法:

 复杂度O(n^3)

首先这个算法使用暴力dp来写的,很容易就会TLE。但是这是一个多源最短路算法,可以求出来任意两点之间的最短距离

示例代码:

技术图片
 1 #include <cstdio>
 2 #include <iostream>
 3 #define INF 0x3f3f3f3f
 4 using namespace std;
 5 int n,m,t,a,b,c;
 6 int f[105][105];
 7 int main()
 8 {
 9     //有n个端点,m条边 
10     cin >> n >> m >> t;
11     //初始化 
12     for (int i=1;i<=n;i++)
13         for (int j=1;j<=n;j++)
14         {
15             if (i==j) f[i][j]=0;
16             else f[i][j]=INF;
17         }
18     //输入边 
19     for (int i=1;i<=m;i++)
20     {
21         scanf("%d%d%d",&a,&b,&c);
22         f[a][b]=c;
23     }
24     //核心代码 
25     for (int k=1;k<=n;k++)
26         for (int i=1;i<=n;i++)
27             for (int j=1;j<=n;j++)
28                 f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
29     //运行完算法之后,f[x][y]里面就是x与y之间的最短距离 
30     return 0;
31 }
View Code

 

例题:UVA10048

 

Dijkstra算法:

算法过程:

给你n个点m条边,你要求x到y的最短距离。这个时候你首先用从x为起点的边来处理一遍控制最短距离的数组dis[](数组初始化dis[x]=0,其他都是正无穷)。然后再用距离x最近的点(设为x1),用以x1为起点的边在来处理一遍dis数组。这个时候dis[x1]里面的值就是x->x1的最短距离。原因就是在所有边都是正数的情况下,那么肯定不可能从x通过一个第三者中转导致x->x1的距离变得更短

 

是一个单源最短路算法

优点:普通算法复杂度:O(N*N),加堆优化:O(N*logN)
缺点:不能处理负权边

例题:Til the Cows Come Home

贝西在田野里,她想回到谷仓,在农夫约翰早上叫醒她挤奶之前尽可能多睡一会儿。贝西需要美容觉,所以她想尽快回来。农夫约翰的田里有N个(2 <= N <= 1000)个界标,唯一的编号是1..地标是谷仓;贝茜整天站在里面的小树林是地标性的N.奶牛在田野里用T (1 <= T <= 2000)在地标之间不同长度的双向牛道。贝西对自己的导航能力不太自信,所以一旦她开始了,她总是沿着一条路线走到底。根据各地标之间的步道,确定贝西返回谷仓的最小距离。可以保证存在这样的路由。
输入*第一行:两个整数:T和N
第2行 . .T+1:每一行都用三个空格分隔的整数来描述一个轨迹。前两个整数是路线经过的地标。第三个整数是步道的长度,范围1..100。
输出*第1行:单个整数,贝茜从地标N到地标1的最小距离。

样例输入
5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100
样例输出
90

 

加堆优化+代码:

技术图片
 1 //Dijkstra迪杰斯特拉+堆优化(邻接矩阵存图)
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<vector>
 8 using namespace std;
 9 #define MAX 0xffffff
10 struct shudui1
11 {
12     int start,value;
13     bool operator < (const shudui1 q)const
14     {
15         return value<q.value;
16     }
17 }str1;
18 struct shudui2
19 {
20     int start,value;
21 }str2;
22 int v[1005];
23 priority_queue<shudui1>r; //里面的数据默认是从小到大排序,这样就不用通过for循环遍历在每一次找v里面的最小值,可以直接找到最小值,减少代码运行次数
24 int a,s,d,f,g;
25 vector <shudui2>w[2005];  //将每一个起点的值作为数组的标识
26             //例如,1 2 3这一组数据,就是说1连接着2,那就把所有1能到的地方存到这个里面
27 int main()
28 {
29     scanf("%d%d",&a,&s);
30     for(int i=1;i<=s;++i)
31         v[i]=MAX;
32     while(a--)
33     {
34         scanf("%d%d%d",&d,&f,&g);
35         str2.start=f;
36         str2.value=g;
37         w[d].push_back(str2);
38         str2.start=d;
39         str2.value=g;
40         w[f].push_back(str2);
41     }
42     v[s]=0;
43     str1.start=s;
44     str1.value=0;
45     r.push(str1);
46     while(!r.empty())
47     {
48         int x,y;
49         str1=r.top();
50         r.pop();
51         x=str1.start;
52         y=str1.value;
53         if(v[x]<y) continue;
54         //说明在这个点再此之后又入队了
55         //此次出队的并不是s到这个点的最短路,
56         //所以在这次更新前点v所连的点已经更过一次了
57         //所以后面也不会进行松弛操作
58         int len=w[x].size();
59         for(int i=0;i<len;++i)
60         {
61             str2=w[x][i];
62             if((v[x]+str2.value<v[str2.start]))
63             {
64                 v[str2.start]=v[x]+str2.value;
65                 str1.start=str2.start;
66                 str1.value=v[str2.start];
67                 r.push(str1);
68             }
69         }
70     }
71     printf("%d\n",v[1]);
72     return 0;
73 }
View Code

 

Spay算法(bellman-Ford优化):

 

算法过程:

给你n个点m条边,你要求x到y的最短距离。这个时候你要枚举每一条边u->v,权值为w,看可不可以通过dis[v]=dis[u]+w来找到dis[v]的更小值(数组初始化dis[x]=0,其他都是正无穷)。在第一轮的松弛之后,得到的是“只经过一条边”到达其余各顶点的最短路径长度。第二轮的时候,得到的是“只经过二条边”到达其余各顶点的最短路径长度。那我们只需要经过n-1轮次的循环就可以了,因为在一个有n个顶点的图中,任意两点之间的距离最多包含n-1边

 

Bellman-Ford这种写法相当暴力, 直接循环nodeNum次, 每次枚举每一条边, 假如这条边可以用于松弛源点到端点的距离, 则进行松弛. 至于判断负环, 再枚举一遍所有边, 假如存在边仍能用于松弛, 则说明存在负权回路.

关于SPFA的时间复杂度,不好准确估计,一般认为是 OkE),k是常数。可处理负边,可判断负环

 

具体看这里

 

仍以Til the Cows Come Home 为例题:

技术图片
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<queue>
 4 #include<algorithm>
 5 #include<iostream>
 6 using namespace std;
 7 const int INF =0xfffff;
 8 const int MAX =2005;
 9 int w[MAX][MAX];
10 int d[MAX];
11 int vis[MAX];
12 queue<int>q;
13 bool spay(int s,int n)   //这个可以用来判断有没有负环的存在
14 {
15     d[s]=0;
16     int cnt=0;
17     q.push(s);
18     q.push(cnt);
19     vis[s]=1;
20     while(!q.empty())
21     {
22         int x=q.front();
23         q.pop();
24         cnt=q.front();
25         q.pop();
26         vis[x]=0;
27         if(cnt>n) return 0;  //这个是用来判断有没有负环,没有负环的情况最多只用查询其n-1个顶点,多于n个那就不正常了
28         for(int i=1;i<n;++i) //本体是从n点到其他点,所以n点不需要再回到n点,可以不遍历
29         {
30             if(d[i]>d[x]+w[x][i])
31             {
32                 d[i]=d[x]+w[x][i];
33                 if(!vis[i])
34                 {
35                     q.push(i);
36                     q.push(cnt+1);
37                     vis[i]=1;
38                 }
39             }
40         }
41     }
42     return 1;
43 }
44 int main()
45 {
46     int n,m;
47     scanf("%d%d",&n,&m);
48     memset(w, 0x3f, sizeof(w));
49     for(int i=1;i<=m;++i)
50         d[i]=INF;
51     while(n--)
52     {
53         int a,s,d;
54         scanf("%d%d%d",&a,&s,&d);
55         if(w[a][s]>d)   //防止重边
56         w[a][s]=d;
57         if(w[s][a]>d)
58         w[s][a]=d;
59     }
60     spay(m,m);
61     printf("%d\n",d[1]);
62     return 0;
63 }
View Code

 

链接表代码:

技术图片
 1 #include <stdio.h>
 2 #include<string.h>
 3 #include <iostream>
 4 #define INF 0x3f3f3f3f
 5 using namespace std;
 6 const int maxn=1005;
 7 struct edge
 8 {
 9     int u,v,w,next;    
10 }e[maxn*maxn];  //如果题目上没有说,那就是n*n条边,n是点 
11 int head[maxn],cnt;
12 void add_edge(int x,int y,int z){  //链接表 
13     e[cnt].u=x;
14     e[cnt].v=y;
15     e[cnt].w=z;
16     e[cnt].next=head[x];
17     head[x]=cnt++;
18 }
19 int main(){
20     cnt=0;
21     int x,y,z;
22     while(~scanf("%d%d%d",&x,&y,&z)){
23         add_edge(x,y,z);
24     }
25     for(int i=0;i<cnt;++i) //打印 
26     {
27         printf("%d %d %d\n",e[i].u,e[i].v,e[i].w);
28     }
29     return 0;
30 } 
View Code

 

最短路总结

标签:void   col   核心   农夫   strong   href   itemid   namespace   php   

原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11623928.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!