Dijkstra算法O (N2)

用来计算从 一个点到其他所有点的最短路径的算法 ,是一种 单源最短路径算法 。也就是说, 只能计算起点只有一个的情况
D ijkstra的时间复杂度是 O (N 2 ) ,它 不能处理存在负边权的情况
算法描述:
       设起点为 s dis[v] 表示从 s v 的最短路径, pre[v] v 的前驱节点,用来输出路径。
       a)初始化: dis[v]= (v s); dis[s]=0; pre[s]= 0 ;
       b) For (i = 1; i <= n ; i++)
            1. 在没有被访问过的点中找一个顶点 u 使得 dis[u] 是最小的。
            2.u 标记为已确定最短路径
            3.For u 相连的每个未确定最短路径的顶点 v
              if  ( dis[u]+w[u ][ v] < dis[v] )
               {
                  dis[v] = dis[u] + w[u ][ v];
                  pre[v] = u;
               }
        c)算法结束: dis[v] s v 的最短距离; pre[v] v 的前驱节点,用来输出路径。
算法实现步骤:
    设图G用邻接矩阵的方式存储在GA中,GA[I,j]=maxint表示vi,vj是不关联的,否则为权值(大于0的实数)。设集合s用来保存已求得的最短路径的终点序号,初始时s=[vi]表示只有源点,以后每求出一个终点vj就把它加入到集合中并作为新考虑的中间结点。
    设数组dist[1..n]用来存储当前求得的最短路径,初始时vi,vj如果是关联的,则dist[j]=权值,否则=maxint,以后,随着考虑的中间结点越来越多,dist[j]可能越来越小。再设一个与dist数组相对应的数组path[1..n],用path[j]来存放当前vi-vj的最短路径上vj点的前驱,初始时为vi的边,如果不存在边,则为0。
    执行时,先从s以外的顶点(即待求出最短路径的终点)所对应的dist数组元素中,找出其值最小的元素(假设为dist[m]),该元素的值就是从源点vi到终点vm的最短路径长度,从对应的path[m]中的顶点开始递归直到源点的序列即为最短路径。接着把vm并入集合s中,然后以vm作为新考虑的中间结点,对s以外的每个顶点vj,比较dist[m]+GA[m,j]和dist[j]的大小,若前者小,表明加入中间结点后可以得到更好的方案,即可求得更短的路径,那么就用dist[m]+GA[m,j]替代原来的dist[j],同时把vm存入到path[j]中。重复以上n-2次,即可在dist数组得到从源点到其余各终点的最短路径长度,对应的path数组中保存着相应的最短路径的终点前驱。
算法执行过程图示分析:
  
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int map[1000][1000];
 6 int vis[1000];
 7 int dis[1000];
 8 int path[1000];
 9 int n,m,w;
10 int e;
11 const int maxn=999999;
12 void df(int);
13 void print(int, int);
14 int main()
15 {
16     cin>>n>>m;
17     memset(dis,maxn,sizeof(dis));
18     memset(map,maxn,sizeof(map));
19     for(int i=1;i<=m;i++)
20      {
21          int x,y;
22          cin>>x>>y>>w;
23          map[x][y]=map[y][x]=w;
24      }
25     memset(vis,0,sizeof(vis));
26     int a;
27     cin>>a>>e;
28     df(a);
29     print(a,e);
30 } 
31 void df(int s)
32 {
33     for(int i=1;i<=n;i++)
34      {
35          dis[i]=map[s][i];
36          if(dis[i]!=maxn)
37           {
38               path[i]=s;
39           }
40         else path[i]=0;
41      }
42      vis[s]=1;
43      dis[s]=0;
44      int k,min1;
45      for(int i=1;i<=n-1;i++)
46       {
47           k=s;
48           min1=maxn;
49           for(int j=1;j<=n;j++)
50            {
51                if(dis[i]<min1&&vis[j]==0)
52                 {
53                     min1=dis[i];
54                     k=j;
55                 }
56            }
57            vis[k]=1;
58            for(int q=1;q<=n;q++)
59             {
60                 if(vis[q]==0&&dis[q]>dis[k]+map[k][q])
61                  {
62                      dis[q]=dis[k]+map[k][q];
63                      path[q]=k;
64                  }
65             }
66       }
67       cout<<dis[e]<<" ";
68 }
69 void print(int u,int r)
70 {
71     int que[1000];
72     int tot=1;
73     int temp;
74     que[tot]=r;
75     tot++;
76     temp=path[r];
77     while(temp!=u)
78      {
79          que[tot]=temp;
80          tot++;
81          temp=path[temp];
82      }
83      que[tot]=u;
84      for(int i=tot;i>=1;i--)
85       {
86           cout<<que[i]<<"-->"; 
87       }
88 }

 

       
       
       

转载于:https://www.cnblogs.com/lyqlyq/p/6686067.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值