(一)首先明确Dijkstra算法是干什么的
是解决赋权图单源最短路问题的。
(二)算法的基本思想:
先确定始点到某一点的最短通路,然后利用这个结果再去求始点到另一个点的最短通路,直到找到始点a到终点z的最短通路。
(三)算法的基本步骤:
1.将点集V分成两个子集T和S,初始时,将始点a放进T集合,S=V-T,DT(t)=w(a,t),DT(t)表示在集合S中的任一点t到始点a的最短通路,t与a相邻,否则DT(t)为正无穷。
2.找出集合S中DT(t)值最小对应的顶点x(他距离a的距离最短)。将x从S集合中删除,将x放进T集合。如果此时S集合为空集,结束,否则,转到步骤三。
3.对集合S中的每一个元素t,更新t到a的距离,DT(t)=min(DT(t),DT(x)+w(x,t)),转到步骤二。
(四)三点说明
1.Dijkstra算法只能解决权值为正的赋权图的单源最短路问题。
2.每个点到始点的最短距离都已经求出。
3.考虑重边。
1 void Dijkstra(int n,int x)//n表示n个结点,x表示源点
2 {
3 int i,p,j,min;
4 for (i=1;i<=n;i++)//初始化
5 {
6 dis[i]=map[x][i];//dis[i]表示x到i节点的最短路,map[i][j]表示i节点到j节点的距离, i,j相邻
7 visited[i]=0;
8 }
9 visited[x]=1;//将x结点放入T集合
10 for (i=1;i<=n;i++)
11 {
12 min=INF;
13 for (j=1;j<=n;j++)
14 {
15 if(!visited[j] && dis[j]<min)//从S集合中找一个到x节点最近的点J
16 {
17 p=j;
18 min=dis[j];
19 }
20 }
21 visited[p]=1;//将J节点放进T集合
22 for (j=1;j<=n;j++)
23 {
24 if(!visited[j] && dis[p]+map[p][j]<dis[j])//将S集合中的所有节点到X节点的距离更新一遍
25 {
26 dis[j]=dis[p]+map[p][j];
27 }
28 }
29 }
30 }
下面放已经AC的题
HDU1874
1 #include <iostream>
2 #include <cstring>
3 #include <stdio.h>
4
5 using namespace std;
6 int n,m;
7 int map[210][210],dis[210],visited[210];
8 const int inf=1<<30;
9 void Dijkstra(int x,int y)
10 {
11 int min,i,j,pos;
12 memset(visited,0,sizeof(visited));
13 for(i=0;i<n;i++)
14 {
15 dis[i]=map[x][i];
16 }
17 visited[x]=1;
18 for(i=1;i<n;i++)
19 {
20 min = inf;
21 for(j=0;j<n;j++)
22 {
23 if(dis[j]<min&&!visited[j])
24 {
25 pos=j;
26 min=dis[j];
27 }
28 }
29 visited[pos]=1;
30 for(j=0;j<n;j++)
31 {
32 if(!visited[j]&&dis[pos]+map[pos][j]<dis[j])
33 dis[j]=dis[pos]+map[pos][j];
34 }
35 }
36
37 }
38 int main()
39 {
40 int start,end,j,a,b,t,i;
41 while(~scanf("%d%d",&n,&m))
42 {
43 for(i=0;i<n;i++)
44 {
45 for(j=0;j<n;j++)
46 map[i][j]=inf;
47 map[i][i]=0;
48 }
49 while(m--)
50 {
51 scanf("%d%d%d",&a,&b,&t);
52 if(map[a][b]>t)
53 map[a][b]=map[b][a]=t;
54 }
55 scanf("%d%d",&start,&end);
56 Dijkstra(start,end);
57 printf("%d
",dis[end]==inf?-1:dis[end]);
58 }
59 return 0;
60 }
HDU2544优先队列解决
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cstdlib>
5 #include<cmath>
6 #include<algorithm>
7 #include<stack>
8 #include<queue>
9 #include<vector>
10 using namespace std;
11 #define INF 0x3f3f3f3f //定义一个很大的数
12 struct Node
13 {
14 int num,val; //存放结点编号和到初始点的距离
15 }nod;
16 priority_queue<Node> qq;; //优先从小到大
17 bool operator < (Node a,Node b)
18 {
19 if(a.val == b.val) return a.num>b.num;
20 return a.val>b.val; //先出小
21 }
22 int book[100]; //检查这个点是否用过
23 int dis[100]; //到原点最短距离
24 int D[100][100]; //记录路径长度
25 int V,E;
26 int main()
27 {
28 int a,b,d;
29 while(cin>>V>>E && V&& E) //输入顶点数和边数
30 {
31 while(!qq.empty()) qq.pop(); //清空
32 memset(book,0,sizeof(book));
33 memset(D,-1,sizeof(D));
34 for(int i=0;i<E;i++)
35 {
36 cin>>a>>b>>d;
37 D[a][b] = D[b][a] = d;
38 }
39 for(int i=2;i<=V;i++)
40 dis[i]=INF;
41 dis[1]=0;
42 nod.num=1;
43 nod.val=0;
44 qq.push(nod); //将起点放入队列
45 while(!qq.empty()) //不为空时
46 {
47 for(int i=2;i<=V;i++)
48 {
49 if(D[qq.top().num][i] != -1 &&dis[i]>dis[qq.top().num] + D[qq.top().num][i])
50 {
51 dis[i]=dis[qq.top().num] + D[qq.top().num][i];
52 nod.num=i; nod.val=dis[i];
53 qq.push(nod);
54 }
55 }
56 qq.pop();
57 }
58 cout<<dis[V]<<endl;
59 }
60 return 0;
61 }