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