dijkstra算法和Floyd算法

旧时模样 提交于 2019-12-28 11:33:45

dijkstra算法及其优化

dijkstra算法用来求权值均为非负的单源最短路径算法。

用于计算单个节点到其他节点的最短路。

特点:以起始点为中心向外层层扩展,直到扩展到终点为止。 本质是贪心算法。

算法思路:(一张图就能概括)

图片来源

不做任何处理的时间复杂度为O(n^2);

代码:

 

 1 int dis[N][N];
 2 int cost[N][N];
 3 int used[M];
 4 int low[M];
 5 int st,end;
 6 int n;
 7 void Dijkstra()
 8 {
 9     int i,j;
10     int pos;
11     memset(used,0,sizeof(used));
12     for(i=1;i<=n;++i)//第一次给low,less赋值
13     {
14         low[i]=dis[st][i];//各点到st的距离
15     }
16     used[st]=1;
17     for(i=1;i<n;++i)//找n-1个点
18     {
19         int min = INF;
20         for(j=1;j<=n;++j)//寻找权值最小的(相当于排序)
21         {
22             if(!used[j]&&min>low[j])
23             {
24                 min=low[j];
25                 pos=j;
26             }
27         }
28         used[pos]=1;//标记flag
29         for(j=1;j<=n;++j)
30         {
31             if(!used[j] &&  low[j]>low[pos]+dis[pos][j]){
32                 low[j]= low[pos]+dis[pos][j];//最短路径
33 
34           }
35 
36         }
37 
38     }
39 
40 }        

 

 

 

优先队列优化:

使用vector和priority_queue优化。

复杂度应为O(ElogV)

代码实现

 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #define INF 1e7
 8 #define N 1005
 9 using namespace std;
10 struct edg{
11     int to,val;
12     friend bool operator < (const edg & a,const edg & b){
13         return a.val >b.val;
14     }
15 };
16 vector < edg > v[N];
17 int vis[N];
18 int low[N];
19 void dijskra(int root,int n){
20     priority_queue < edg >q;
21     memset(vis,0,sizeof(vis));
22     for(int i=1;i<=N;i++){
23         low[i]=INF;
24     }
25     edg x;
26     x.to=root;
27     x.val=0;
28     q.push(x); //以root为第一个遍历的结点
29     low[root]=0;
30     int ans=0;
31     while(!q.empty()){
32         edg now=q.top();
33         q.pop();
34         if(vis[now.to]==1){
35             continue;
36         }
37         vis[now.to]=1; 
38         ans++;
39         if(ans == n) break;
40         for(int i=0;i<v[now.to].size();i++){
41             edg tmp=v[now.to][i];
42             if(!vis[tmp.to]&&(low[tmp.to]>low[now.to]+tmp.val)){
43                 low[tmp.to]=low[now.to]+tmp.val;
44                 q.push({tmp.to,low[tmp.to]}); // 将tmp.to结点以及它到root的最短路径值压入队列
45             }
46         }
47     }
48 }
49 int main(){
50     int x, y, z;
51     int n,m;
52      while(cin >> n >> m){
53         if(n==0&&m==0) break;
54          for(int i = 0; i < 1000; i++)
55             v[i].clear();
56          for(int i = 0; i < m; i ++){
57             cin >> x >> y >> z;
58             v[x].push_back({y, z});
59             v[y].push_back({x, z});
60          }
61         dijskra(1,n);
62         printf("%d\n",low[n]);
63      }
64 }

 

 

 

Floyd算法

主要用于解决权值为负的最短路问题。

特点:容易理解。本质是动态规划。

时间复杂度为O(n^3)

算法思路:从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。 

模板:

 

 1 #include<iostream>
 2 #include<algorithm>  
 3 #define inf 1000000;  
 4 using namespace std;  
 5 int len[1000][1000],dis[1000][1000];
 6 int main()  
 7 {  
 8         int i,n,j,k;  
 9         memset(len,1000000,sizeof(len));  
10           
11         for(i=0;i<n;i++)  
12         {  
13             for(j=0;j<n;j++)  
14             {  
15                 for(k=0;k<n;k++)  
16                 {  
17                     if(len[j][k]>len[j][i]+len[i][k])  
18                         len[j][k]=len[j][i]+len[i][k];  
19                 }  
20             }  
21         }  
22     }  

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!