• 单源最短路径 dijkstra


    dijkstra是单源最短路径算法,要两个数组来维护需要的信息

    dis[i]用来维护起始点到i点的最短距离,初始化为一个很大的数字 0x3f3f3f3f

    vis[i]用来维护是否访问过该点,初始化为0,即没有访问过

    dijkstra算法有朴素版实现和优先队列优化版本

    朴素版

    dijkstra算法思路如下:

    1、确定一个起始点begin

    2、让dis[begin] = 0

    3、选取一个让dis[s]最小,且没有访问过的点s(第一次访问的节点是起始点)

    4、让vis[s] = 1表示已经访问过s点

    5、对于与s相连的点i,比较dis[s]+s、i之间的距离和dis[i]的大小,

    如果前者比较小,说明找到一条从起始点到i点更短的路,就要更新dis[i]

    让dis[i] = dis[s] + s、i之间的距离。

    如果前者比较大,说明没有找到一条从起始点到i点更短的路,不需要更新dis[i]

    6、重复3到5的步骤直到所有节点都被访问过

    7、dis数组更新完毕,当前dis[i]就表示起始点到i点的最短距离

    优先队列优化版

    优化的是步骤3,从原本的遍历所有点比较大小再选取最小的点,

    变成了直接选优先队列的头,时间复杂度从O(n)变为O(logn)

    朴素版的时间复杂度为O(n²) 优化版的时间复杂度为O(nlogn)

    来一个例子

     

    A、B、C、D、E、F点的编号分别为1、2、3、4、5 、6

    假如要计算1号点到其他点的最短距离

    1.就把1号点当作起点

    2.dis[1] = 0,dis[2] = 0x3f3f3f3f,dis[3] = 0x3f3f3f3f,dis[4] = 0x3f3f3f3f,dis[5] = 0x3f3f3f3f,dis[6] = 0x3f3f3f3f

    3.因为dis[1]为0所以这时候dis[1]最小,所以选1号点,vis[1] = 1表示访问过了

    4.1号点选完之后,与1号点相连的点有2号 5号 6号 点

    5.由于dis[2] > dis[1] + 6 所以更新dis[2]  dis[2] = dis[1] + 6

    由于dis[6] > dis[6] + 1 所以更新dis[6]  dis[6] = dis[1] + 1

    由于dis[5] > dis[1] + 5 所以更新dis[5]  dis[5] = dis[1] + 5

    现在dis[1] = 0, dis[2] = 6, dis[3] = 0x3f3f3f3f, dis[4] = 0x3f3f3f3f, dis[5] = 5,dis[6] = 1

    6.继续选下一个点,因为1号点选过了,所以应该选除了1号点之外dis最小的点,即6号点

    7.与6号点相连的有1号 2号 3号 4号 5号

    由于dis[2] > dis[6] + 2 所以更新dis[2] dis[2] = dis[6] + 2

    由于dis[3] > dis[6] + 8 所以更新dis[3] dis[3] = dis[6] + 8

    由于dis[4] > dis[6] + 4 所以更新dis[4] dis[4] = dis[6] + 4

    由于dis[5] < dis[6] + 9 所以不更新

    现在dis[1] = 0,dis[2] = 3, dis[3] = 9,dis[4] = 5,dis[5] = 5,dis[6] = 1

    继续选没有选过的点直到所有的点都被选过

    洛谷P3371 

    代码 

    1. #include
    2. using namespace std;
    3. const int MAXN = 100010;
    4. int n,m;
    5. struct edge{
    6. int v,w;
    7. };
    8. int dis[MAXN],vis[MAXN];
    9. void dijkstra (int begin, vector v[]){
    10. memset(dis,0x3f3f3f3f,sizeof(dis));
    11. dis[begin] = 0;
    12. for(int i = 1;i <= n; i++){
    13. int s = 0,min = 0x3f3f3f3f;
    14. vis[s] = 1;
    15. for(int j = 1;j <= n; j++){
    16. if(!vis[j] && dis[j] < min){
    17. min = dis[j];
    18. s = j;
    19. }
    20. }
    21. vis[s] = 1;
    22. for(auto x : v[s]){
    23. if(dis[x.v] > dis[s] + x.w)
    24. dis[x.v] = dis[s] + x.w;
    25. }
    26. }
    27. };
    28. int main()
    29. {
    30. ios::sync_with_stdio(false);
    31. cin.tie(0),cout.tie(0);
    32. int s,t1,t2,w;
    33. cin >> n >> m >> s;
    34. vector v[n+1];
    35. for(int i = 1;i <= m; i++){
    36. cin >> t1 >> t2 >> w;
    37. v[t1].push_back({t2,w});
    38. }
    39. dijkstra(s, v);
    40. for(int i = 1;i <= n; i++){
    41. if(dis[i] < 0x3f3f3f3f)
    42. cout << dis[i] << " ";
    43. else cout << 2147483647 << " ";
    44. }
    45. }

    优先队列优化版

    洛谷P4779

    1. #include
    2. using namespace std;
    3. const int MAXN = 100010;
    4. int n,m;
    5. struct edge{
    6. int v,w;
    7. };
    8. int dis[MAXN],vis[MAXN];
    9. struct info{
    10. int d,v;
    11. bool operator < (const info & a) const {
    12. return d > a.d;
    13. }
    14. };
    15. int main()
    16. {
    17. ios::sync_with_stdio(false);
    18. cin.tie(0),cout.tie(0);
    19. int s,t1,t2,w;
    20. cin >> n >> m >> s;
    21. vector v[n+1];
    22. for(int i = 1;i <= m; i++){
    23. cin >> t1 >> t2 >> w;
    24. v[t1].push_back({t2,w});
    25. }
    26. function<void(int)> dijkstra = [&](int begin){
    27. memset(dis,0x3f3f3f3f,sizeof(dis));
    28. dis[begin] = 0;
    29. priority_queue< info > pq;
    30. pq.push({0,begin});
    31. while(!pq.empty()){
    32. int vi = pq.top().v;
    33. pq.pop();
    34. if(vis[vi]) continue;
    35. vis[vi] = 1;
    36. for(auto x : v[vi]){
    37. if(dis[x.v] > dis[vi] + x.w) {
    38. dis[x.v] = dis[vi] + x.w;
    39. pq.push({dis[x.v],x.v});
    40. }
    41. }
    42. }
    43. };
    44. dijkstra(s);
    45. for(int i = 1;i <= n; i++){
    46. cout << dis[i] << " ";
    47. }
    48. }

  • 相关阅读:
    没钱,没人,没经验?传统制造型企业如何用无代码实现转型
    哪些人更容易受到网络攻击?
    “勤学会”火爆来袭
    TDSQL-C 真·秒级启停:连接断了,又没断
    MyBatis-Plus
    【对列表中的每个元素做函数映射map()】
    Java 端口扫描器示例
    计算机神经网络专业前景,计算机神经网络是什么
    数据结构与算法-顺序表
    vue之封装tab类组件
  • 原文地址:https://blog.csdn.net/DaoCaoRen___/article/details/126373970