三种最短路径的模板

1.迪杰斯特拉(dijkstra):

(1)朴素版:

 1 void dijkstra()
 2 {
 3     int g,minx; 
 4     z[s]=1;//起点标记 
 5     for(int i=1;i<=n;i++)//初始化 
 6     {
 7         dist[i]=v[s][i];
 8     }
 9     for(int i=1;i<=n;i++)//n个节点,找n次 
10     {
11         minx=INT_MAX;
12         for(int j=1;j<=n;j++)
13         {
14             if(!z[j]&&(dist[j]<minx))//寻找未被标记的最小节点 
15             {
16                 minx=dist[j];
17                 g=j;
18             }
19          }
20          z[g]=1;//标记被找到的最小节点
21          for(int k=1;k<=n;k++) 
22          {
23              if(!z[k]&&dist[k]>(dist[g]+v[g][k]))//更新节点(s->k大于s->g->k)
24              {
25                  dist[k]=dist[g]+v[g][k];
26              }
27          }
28     }
29  } 

(2)邻接表存图+优先队列优化

 1 void dijkstra()
 2 {
 3     //初始化 
 4     fill(dis,dis+maxn,inf);
 5     dis[s]=0;
 6     q.push(make_pair(0,s));//第一维存储dis的相反数:把大根堆转化为小根堆 
 7     //直到队列为空,没有更短路径 
 8     while(!q.empty)
 9     {
10         //获取队头元素,有push就有pop 
11         int x=q.top().second;
12         q.pop();
13         //是否以及添加进图中 
14         if(vis[x]==1)
15         continue;
16         vis[x]=1;//添加 
17         //松弛操作,基于终点 
18         for(int i=head[x];i!=0;i=edge[i].next)
19         {
20             int to=edge[i].to;
21             if(!vis[to]&&dis[to]>dis[x]+edge[i].dis)
22             {
23                 dis[to]=dis[x]+edge[i].dis;
24                 //入队 
25                 q.push(make_pair(-dis[to],to)); 
26             }
27         }
28     }
29  } 

2.贝尔曼福特(bellman_ford):

(1)朴素+优化:

 1 void bellman_ford()
 2 {
 3     //初始化 
 4     fill(dis,dis+maxn,inf);
 5     dis[s]=0; 
 6     //核心:两层循环 
 7     for(int i=1;i<=n-1;i++)
 8     {
 9         check=0; 
10         for(int j=1;j<=m;j++)
11         {
12             //松弛操作,基于起点 
13             if(dis[u[i]]!=inf&&dis[v[i]]>dis[u[i]]+w[i])
14             {
15                 dis[v[i]]=dis[u[i]]+w[i];
16                 check=1;
17             }
18         }
19         //如果没有进行新的松弛操作,说明已经是最短路径,结束循环便可 
20         if(check==0)
21         break;
22     }
23     //判断是否有负权回路 
24     for(int i=1;i<=n-1;i++)
25     {
26         for(int j=1;j<=m;j++)
27         {
28             if(dis[v[i]]>dis[u[i]]+w[i])
29             {
30                 flag=1;
31                 break;
32             }
33         }
34     }
35     //输出 
36     if(flag==0)
37     {
38         //输出最短路径 
39      } 
40      else
41      //有负权回路 
42  } 

(2)队列优化,邻接表存图:

 1 //first[],next[],u[],v[],w[]:邻接表
 2 //book标记是否在队列中 
 3 void bellman_ford()
 4 {
 5     //初始化 
 6     fill(dis,dis+maxn,inf);
 7     dis[s]=0;
 8     book[s]=1;
 9     q.push(s);
10     //循环,队列不为空
11     while(!q.empty())
12     {
13         //取队头 
14         int k=first[q.front()];
15         //取的顶点在已有范围内 
16         while(k!=-1)
17         {
18             //松弛操作 
19             if(dis[v[k]]>dis[u[k]]+w[k])
20             {
21                 dis[v[k]]=dis[u[k]]+w[k];
22             //顶点v[k]不在队列中,则加入到队列并标记 
23             if(book[v[k]]==0)
24             {
25                 q.push(k[v]);
26                 book[v[k]]=1;
27             }
28             }
29             //取下一个k,链表结构 
30             k=next[k];
31         }
32         //出队 
33         q.pop();
34     }
35 }

3.弗洛伊德算法(floyed):

 1 //基于已有的矩阵 
 2 void floyed()
 3 {
 4     //初始化 
 5     cin>>n>>m; 
 6     for(int i=1;i<=n;i++)
 7     {
 8         for(int j=1;j<=n;j++)
 9         {
10             //初始化矩阵对角线为0 
11             if(i==j)
12             dis[i][j]=0;
13             else
14             dis[i][j]=inf;
15         }
16      } 
17      for(int i=1;i<=m;i++)
18      {
19          cin>>u>>v>>w;
20          dis[u][v]=w;
21      }
22      //核心,三个循环,5行 
23      for(int k=1;k<=n;k++)
24      {
25          for(int i=1;i<=n;i++)
26          {
27              for(int j=1;j<=n;j++)
28              {
29                  if(dis[i][j]>dis[i][k]+dis[k][j])
30                  {
31                      dis[i][j]=dis[i][k]+dis[k][j];
32                  }
33              }
34          }
35      }
36 }

三种算法的时间,空间复杂度以及适用情况

 

 ——《啊哈!算法》

posted @ 2022-05-01 16:03  格蕾  阅读(37)  评论(0)    收藏  举报