首页 > 代码库 > Dijkstra算法O (N2)

Dijkstra算法O (N2)

用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法。也就是说,只能计算起点只有一个的情况
Dijkstra的时间复杂度是O (N2),它不能处理存在负边权的情况
算法描述:
       设起点为sdis[v]表示从sv的最短路径,pre[v]v的前驱节点,用来输出路径。
       a)初始化:dis[v]=(vs); 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]sv的最短距离;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 }

 

             
             
             

Dijkstra算法O (N2)