• 最小生成树专题1 最小生成树-Prim算法


    题目:

    样例1:

    输入
    1. 4 5
    2. 0 1 3
    3. 0 2 2
    4. 0 3 3
    5. 2 3 1
    6. 1 2 1
    输出
    4

     样例2:

    输入
    1. 3 1
    2. 0 1 1
    输出
    -1

    思路:

            Prim 算法和 朴素版的 Dijkstra 有点类似,也叫做 朴素版Prim算法,但也还是有点区别。

    Dijkstra 中,只要起点到目的点的最短距离。

    最小生成树,表示   不定某个起点和终点,要求遍历完所有点的 最短距离。

    所以,朴素版的 Prim 和 朴素版的 Dijkstra 很相似。

    区别在于更新 dist 的时候,Dijkstra 更新的是距离,Prim 更新的是 集合之间的最短边。

    1. for(int j = 0;j < n;++j)
    2. {
    3. dist[j] = min(dist[j],g[t][j]);
    4. }

    最小生成树中,是 找 集合到集合之间的  最小边,  Dijkstra最短距离是 节点之间的最小距离。

    代码详解如下:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define endl '\n'
    8. #define YES puts("YES")
    9. #define NO puts("NO")
    10. #define INF 0x3f3f3f3f
    11. #define umap unordered_map
    12. #define All(x) x.begin(),x.end()
    13. #pragma GCC optimize(3,"Ofast","inline")
    14. #define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
    15. using namespace std;
    16. const int N = 500 + 10;
    17. int n,k;
    18. int g[N][N]; // 存储结点之间的最短边
    19. bool st[N]; // 标记是否遍历过该点
    20. int dist[N]; // 存储集合之间的最短边
    21. inline int Prim()
    22. {
    23. // 初始化集合之间的最短边方案为无穷
    24. memset(dist,INF,sizeof dist);
    25. dist[0] = 0; // 初始化检查起始点最短边方案为 0
    26. int ans = 0; // 存储最小生成树的最短边
    27. for(int i = 0;i < n;++i)
    28. {
    29. int t = -1; // 探头 t 探索每个结点,哪个是最短边
    30. for(int j = 0;j < n;++j)
    31. {
    32. // 如果符合 最短边结点,且为遍历过该结点 那么更新 t
    33. if(!st[j] && (t == -1 || dist[j] < dist[t]))t = j;
    34. }
    35. // 如果存在孤立点 那么肯定无法遍历完所有点,没有最小生成树返回 -1
    36. if(i && dist[t] >= INF) return -1;
    37. st[t] = true; // 标记好已经遍历了 该 t 结点
    38. if(i) ans += dist[t]; // 如果已经开始走动了,那么开始存储集合之间的最短边
    39. for(int j = 0;j < n;++j) dist[j] = min(dist[j],g[t][j]); // 更新所有最短边,即 t 点到 j 点之间的最短边
    40. }
    41. if(ans >= INF) return -1; // 如果存在孤立点,返回 -1
    42. return ans; // 返回最小生成树最短边
    43. }
    44. inline void solve()
    45. {
    46. // 初始化集合之间的边长为无穷
    47. memset(g,INF,sizeof g);
    48. cin >> n >> k;
    49. while(k--)
    50. {
    51. int a,b,c;
    52. cin >> a >> b >> c;
    53. // 存储结点之间最短边
    54. g[a][b] = g[b][a] = min(g[a][b],c);
    55. }
    56. cout << Prim() << endl;
    57. }
    58. int main()
    59. {
    60. // freopen("a.txt", "r", stdin);
    61. IOS;
    62. int _t = 1;
    63. // cin >> _t;
    64. while (_t--)
    65. {
    66. solve();
    67. }
    68. return 0;
    69. }

    最后提交:

  • 相关阅读:
    Linux 服务器(Ubuntu) 安装 golang记录
    H指数----题解报告
    阿尔兹海默病智能诊断
    Toxel 与 PCPC II
    设计模式 -- 工厂模式(Factory Pattern)
    【嵌入式开发 Linux 常用命令系列 7.2 -- awk 找到空格并插入字符】
    Avalonia 部署到麒麟信安操作系统
    【图像处理小知识】PIL Image 中的P和L模式
    NDK交叉编译FFmpeg安卓编译ffmpeg
    C++进阶-STL string容器的基本介绍
  • 原文地址:https://blog.csdn.net/hacker_51/article/details/134054687