zoukankan      html  css  js  c++  java
  • 最小生成树Prim

    首先解释什么是最小生成树,最小生成树是指在一张图中找出一棵树,任意两点的距离已经是最短的了。

    算法要点:

    1、用book数组存放访问过的节点。

    2、用dis数组保存对应下标的点到树的最近距离,这里要注意,是对树最近的距离,而不是源点,这和单源最短路径是有区别的。

    3、用maps数组保存边的关系。

    4、每次先找到离树最近的且没有被访问过的点,以这点的所有边去更新dis数组,也就是更新和树的最近距离。

    算法模型:

    for(循环n-1次,因为默认1点为起始点,已经被访问了)

    {

             for(循环n次。)

            {

                     利用book数组,找到dis中的最近点,且没被访问过的点。

            }

            记录该点被访问,记录当前dis该点的距离存放至答案。

             for(循环n次)

            {

                   利用book数组,找到没有被访问过的点,用该点的所有边更新dis数组,也就是更新和树的最近距离。

            }

    }

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    
    using namespace std;
    /*最小生成树Prim未优化版*/
    
    int book[100];//用于记录这个点有没有被访问过
    int dis[100];//用于记录距离树的距离最短路程
    int MAX = 99999;//边界值
    int maps[100][100];//用于记录所有边的关系
    
    int main()
    {
        int i,j,k;//循环变量
        int n,m;//输入的N个点,和M条边
        int x,y,z;//输入变量
        int min,minIndex;
        int sum=0;//记录最后的答案
        
        cin>>n>>m;
    
        //初始化maps,除了自己到自己是0其他都是边界值
        for (i = 1; i <= n; i++)
        {
            for (j = 1; j <= n; j++)
            {
                if(i!=j)
                    maps[i][j] = MAX;
                else
                    maps[i][j] = 0;
            }
        }
                
        for (i = 1; i <= m; i++)
        {
            cin>>x>>y>>z;//输入的为无向图
            maps[x][y] = z;
            maps[y][x] = z;
        }
    
        //初始化距离数组,默认先把离1点最近的找出来放好
        for (i = 1; i <= n; i++)
            dis[i] = maps[1][i];
    
        book[1]=1;//记录1已经被访问过了
    
        for (i = 1; i <= n-1; i++)//1已经访问过了,所以循环n-1次
        {
            min = MAX;//对于最小值赋值,其实这里也应该对minIndex进行赋值,但是我们承认这个图一定有最小生成树而且不存在两条相同的边
            //寻找离树最近的点
            for (j = 1; j <= n; j++)
            {
                if(book[j] ==0 && dis[j] < min)
                {
                    min = dis[j];
                    minIndex = j;
                }
            }
    
            //记录这个点已经被访问过了
            book[minIndex] = 1;
            sum += dis[minIndex];
    
            for (j = 1; j <= n; j++)
            {
                //如果这点没有被访问过,而且这个点到任意一点的距离比现在到树的距离近那么更新
                if(book[j] == 0 && maps[minIndex][j] < dis[j])
                    dis[j] = maps[minIndex][j];
            }
        }
    
        cout<<sum<<endl;
    }
    
    /*
    
    6 9
    2 4 11
    3 5 13
    4 6 3
    5 6 4
    2 3 6
    4 5 7
    1 2 1
    3 4 9
    1 3 2
    Result:19
    
    */

    以上这个算法是没有优化过的,优化的方法很多,堆排序,邻接表等等。有兴趣可以继续看看。

    主要想说的是最小生成树和单源最短路径是有区别的,虽然看起来代码比较像,但是本质有些不同,看到题目的时候,还是要好好去分析使用什么方法去做。

  • 相关阅读:
    MFC单文档中进行plc点云显示
    modbus发送和接收
    测试左移和测试右移
    2021软件测试笔试题
    202106月份总结测试开发面试题
    KuaiShou面试题
    阿拉伯数学手写体。
    GeminiScrollbar
    vue-core-video-player
    webpack
  • 原文地址:https://www.cnblogs.com/linkstar/p/5331349.html
Copyright © 2011-2022 走看看