• 最小生成树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
    
    */

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

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

  • 相关阅读:
    硬件04:反馈与触发器
    硬件03:二进制减法器
    硬件02:二进制加法器
    ASP.NET MVC 表单提交多层子级实体集合数据到控制器中
    微信全局获取并缓存Accesstoken的值
    MySQL 中文显示乱码
    HTML5 Canvas绘图详解 drawImage() 方法 有图有真相!
    [原创]超强C#图片上传,加水印,自动生成缩略图源代码
    微信公共服务平台开发(.Net 的实现)5-------解决access_token过期的问题 .
    2015-10-19深圳面试
  • 原文地址:https://www.cnblogs.com/linkstar/p/5331349.html
Copyright © 2020-2023  润新知