Dijkstra-单源最短路
Dijkstra的介绍我就免了,相信点进来的都知道
Dijkstra算法和prim算法(求最小生成树)有许多相似之处,区别就是dis数组代表的含义不一样
初步学一个算法的时候推荐找一个最基本的题目,别敲别学,不然没什么效果
例题 hdu1874畅通工程续
不过这题有点坑:1.重边的处理2.起点与终点相同的情况注意一下就好了
15ms 1504k
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <cmath>
6 using namespace std;
7
8 #define mem(a) memset(a,0,sizeof(a))
9 #define ll long long
10 const int maxn = 300;
11 const int inf = 0x3f3f3f3f;
12 int a[maxn][maxn];
13 int dis[maxn];
14 int vis[maxn];
15 int n,m;
16 void dijkstra(int u,int v)
17 {
18 int k = u;
19 mem(vis);
20 for(int i = 0; i < n; i++)
21 {
22 if(i == k) dis[i] = 0;
23 else dis[i] = inf;
24 }
25 vis[k] = 1;
26 for(int i = 1; i < n; i++)
27 {
28 m = inf;
29 for(int j = 0; j < n; j++)
30 {
31 if(!vis[j] && m > dis[j])
32 {
33 m = dis[j];
34 k = j;
35 }
36 }
37 vis[k] = 1;
38 for(int j = 0; j < n; j++)
39 if(!vis[j] && dis[j] > dis[k] + a[k][j])
40 dis[j] = dis[k] + a[k][j];
41 }
42
43 }
44
45 int main()
46 {
47 int u,v,w;
48 while(~scanf("%d",&n))
49 {
50 scanf("%d",&m);
51 for(int i = 0; i < n; i++)
52 for(int j = 0; j < n; j++)
53 a[i][j] = (i==j?0:inf);
54 for(int i = 0; i < m; i++)
55 {
56 scanf("%d%d%d",&u,&v,&w);
57 if(w < a[u][v])
58 a[u][v] = a[v][u] = w;
59 }
60 scanf("%d%d",&u,&v);
61 dijkstra(u,v);
62 if(dis[v] == inf) printf("-1\n");
63 else printf("%d\n",dis[v]);
64 }
65 return 0;
66 }
附这题的Floyd算法(感兴趣可以了解下)
dijkstra的优先队列实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream>
2 #include<queue>
3 #include<cstdio>
4 #include<cstring>
5 #include<algorithm>
6 using namespace std;
7 typedef pair<int, int> pii;
8 const int maxn=1e5+5, maxm=2e5+5;
9 struct edge
10 {
11 int t, w; edge * nxt;
12 edge(int to, int len, edge * next){ t=to, w=len, nxt=next; }
13 };
14 edge * head[maxn];
15 void add(int u, int v, int len){ head[u]=new edge(v, len, head[u]); }
16 int dis[maxn], v[maxn], n, m, s;
17
18 void dijkstra(int s)
19 {
20 memset(dis, 0x3f, sizeof dis); //sizeof不是一个函数,而是运算符,这种用法是可以的
21 priority_queue<pii, vector<pii>, greater<pii> > Q; //小根堆
22 dis[s]=0;
23 Q.push(make_pair(0, s));
24 while(!Q.empty())
25 {
26 int x=Q.top().second;
27 if(v[x]) { Q.pop(); continue;} //continue;之前一定要pop掉,否则会死循环
28 else { v[x]=true; dis[x]=Q.top().first; Q.pop();}
29
30 for(edge *p=head[x]; p; p=p->nxt) if (!v[p->t]) Q.push(make_pair(dis[x]+p->w, p->t));
31 }
32 }
33
34 int main()
35 {
36 scanf("%d%d%d", &n, &m, &s);
37 for(int i=1, x, y, z; i<=m; i++) scanf("%d%d%d", &x, &y, &z), add(x, y, z);
38 dijkstra(s);
39 for(int i=1; i<=n; i++) printf("%d ", dis[i]);
40 printf("\n");
41 return 0;
42 }