问题描述:
从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径
Dijkstra算法思想:
该算法是解决单源最短路径的贪心算法,算法先从顶点集合中找到一个到源点最短路径的顶点,并将其从顶点集合中去掉,然后再从剩下的顶点集合中找到一个次最短距离的顶点,并将其从集合中去点,最后到顶点集合为空时,算法结束,最开始选择离源点最近的点t,将其从集合中去掉,再从集合中选择离源点最近的顶点j,因为源点到t已经是到顶点t的最短距离了,如果t是j的邻接点(t到j有边),则可以通过源点到t+t到j的距离,也就是dist[t]+map[t][j]和直接从源点到j的距离作比较选择小的那个距离,更新dist[j],代码中维护四个数组,其中map数组是邻接矩阵,两个顶点i,j有边则将其map[i][j]赋值为边的权值,否则为INF,dist数组为距离数组表示源点到i的最短距离,flag标志数组,p数组表示i的前驱顶点,Dijkstra算法时间复杂度为O(n^2),但是不能处理权值为负数的情况。
执行动画:
代码:
- #include <iostream>
- #include <algorithm>
- #include <stack>
- using namespace std;
- const int N = 100;//最大顶点
- const int INF = 1e7;
- int map[N][N], dist[N], p[N], n, m;
- bool flag[N];//标志顶点有没有被访问过
- void Dijkstra(int u)
- {
- int i, j;
- for (i = 1; i <= n; i++)
- {
- dist[i] = map[u][i];//u到i的距离
- flag[i] = false;
- if (dist[i] == INF)//u不能到i
- {
- p[i] = -1;
- }
- else//i的前驱是u
- {
- p[i] = u;
- }
- }
- dist[u] = 0;
- flag[u] = true;
- for (i = 1; i <= n; i++)
- {
- int temp = INF, t = u;
- for (j = 1; j < n; j++)//找一个离源顶点最近的顶点
- {
- if (!flag[j] && temp > dist[j])
- {
- t = j;
- temp = dist[j];
- }
- }
- if (t == u)return;//没找到
- flag[t] = true;//标记访问
- for (j = 1; j <= n; j++)
- {
- if (!flag[j] && map[t][j] < INF)//没被访问并且t是j的前驱等价与map[t][j]有值
- {
- if (dist[j] > dist[t] + map[t][j])
- {
- dist[j] = dist[t] + map[t][j];
- p[j] = t;
- }
- }
- }
- }
- }
- //打印路径
- void findPath(int u)
- {
- int i,x;
- stack<int> s;
- for (i = 1; i<= n; i++)
- {
- x = p[i];
- while (x != -1)
- {
- s.push(x);
- x = p[x];
- }
- while (!s.empty())
- {
- cout << s.top() << "->";
- s.pop();
- }
- cout << i << " 最短路径:" << dist[i]<<endl;
- }
- }
- int main()
- {
- int i, j;
- int u, v, w;
- cin >> n >> m;
- //map数组初始化
- for (i = 1; i <= n; i++)
- {
- for (j = 1; j <= n; j++)
- {
- map[i][j] = INF;
- }
- }
- while (m--)
- {
- cin >> u >> v >> w;
- map[u][v] = min(map[u][v], w);//邻接矩阵保留最小距离
- }
- int start;
- cin >> start;
- Dijkstra(start);
- for (i = 1; i <= n; i++)
- {
- cout << start << "---" << i << ":";
- if (dist[i] != INF)
- {
- cout << dist[i] << endl;
- }
- }
- findPath(start);
- return 0;
- }