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 }
来源:https://www.cnblogs.com/ISGuXing/p/7632560.html
