最小生成树c++基础

最小生成树的问题等价于:在有n个点,m条边的带权图中,选择n-1条边使得各个点构成一个连通图(无回路)同时使其所选边权值和最小。

在理解掌握基础存图方法后,首先可以使用prim算法解决此问题。

算法基本思想:

1 选取图上任意一顶点;(最开始时)

2 枚举选择该点(已选择的点不选)连接的权值最小的边(同时记录该边对应的顶点nixt,将该点加入已选择的集合)

3 更新点nixt到各点的权值(已选择的不更新)。

重复以上步骤直到n个点都被选择记录。

复杂度:n^2。

代码实现(最难的,比克鲁斯卡尔难)

void prim(){
   bool vis[maxn];//集合内外的标志(当前点是否已经选择)
Int cost[maxn];//存储集合内到集合外顶点的最小值
//非常重要 注意!!!!cost为:当前已选择的nixt点到各点所需花费的距离,若不能到达某点,则其值为无穷大(即边权)。其中cost(L)=s的意义为某点到点L的边的权值(边长)为s,每次选择点nixt时都要更新!!这里比较难理解

    int i,j,minc,nixt,ans=0;//next最小值对应的顶点. 

    memset(vis,0,sizeof(vis));

    memset(cost,0x3f,sizeof(cost));
    //初始化为无穷大
    cost[1]=0;//初始化起始顶点1的花费.从任何一个顶点开始都可以;
    for(i=1;i<=n;i++){
        //枚举n个点
        minc=0x3f3f3f3f;//每次换点肯定更新
        for(j=1;j<=n;j++) //找出该点连接的最短距离(最短边),和所连接的顶点nixt; 
           if (!vis[j]&& cost[j]<minc)//不断更新最短边
                     {
                  minc=cost[j];//记录最短边权
                  nixt=j;//记录对应顶点
              }
                 ans+=minc;//记录最小生成树的值
        vis[next]=true; //选中顶点nixt并入集合内
        for (j=1;j<=n;j++)//更新集合内集合外最短距离数组cost(即点nixt到各点的距离); 
          if ((!vis[j]&& cost[j]>map [next][j])//map数组为邻接矩阵存图,表示已选择的点nixt到某点j距离更新(若本身两点之间没有边相连,前面已经初始化边长为无穷大)                                 
             cost[j]=map [next][j]
//将nixt到点j的距离更新
    }
    return ;    
}
       cout<<ans;

 

 该算法可能根据我的表述,可能听上去近似于一种贪心算法,但其实prim不是一种贪心,他的处理方式很奇妙,如果你没被我前面的语言表达绕迷糊,你可以进来看看。

 https://www.cnblogs.com/lihanyu116/p/14986474.html

 

如有不足,欢迎指出,谢谢

 

posted @ 2021-07-07 17:21  暂未成功人士  阅读(162)  评论(0编辑  收藏  举报