【难忘今宵】第一阶段day2

前两天学完了数理统计,想再花四天时间把微观经济学给学完了,只是笔记本不知道够不够用啊啊啊QwQ
寒假结束前有一次集训队二招,不知道其他人准备的怎么样了。
今天复习的算法是最小生成树,最小生成树在运筹学和离散数学中都有提及,目前我印象中的算法有:避圈法、整树加边法,后来才发现其实这俩前者就是kruskal后者就是prim。。( ̄▽ ̄)"

1.Prim算法

数据结构:

二维矩阵g[][]存图;
lowcost[i]为第i个点到整棵树的距离,若没有路则为INF;
mst[i]表示以第i个点为终点,到整棵树距离最短的那条边对应的起点,即对应lowcost[i]的起点,当第i个点加入生成树后令其mst[i]=0。

主要思想:

整树加边法:任选一个起点作为树的初始化,加入一条离整棵树最近的边(点),再把整个树作为一个整体,找下一个离整棵树最近的边(点)加入树中,直到所有点都加入。

实现:

  1. 初始化:g[][]存图,默认第一个点为起点,lowcost[]均为到起点的距离(除起点为0),mst[]均为起点标号1;
  2. 操作——找:找出lowcost[]中最小非零点i(边);
   if (lowcost[j] < min && lowcost[j] != 0){
       min = lowcost[j];
       minid = j;
   }
  1. 操作——加入:加入最小生成树中即lowcost[i]=0,mst[i]=0;
  2. 操作——更新:不用重新扫一遍图!用刚加入的点比较一轮即可:
  for (j = 2; j <= n; j++){
      if (graph[minid][j] < lowcost[j]){
          lowcost[j] = graph[minid][j];
          mst[j] = minid;
      }
  }
  1. 跳出:当生成树中点数为n时即可跳出(循环n次以上三个操作步骤)。

这个博主图画的很好,数组名字我也是按他的取的:
https://blog.csdn.net/yeruby/article/details/38615045

2.kruskal算法

数据结构:

结构体数组a:边集数组,每个节点有三个数据存储一条边:起点a终点b权值
父节点数组par[i]:表示第i个点的父节点
并查集=父节点数组par[]+操作函数(建树操作,合并操作,找爸爸操作共三个基本函数)

主要思想:

避圈法,所谓避圈就是俩点不能属于同一集合。

  1. 初始化:将图看做一个森林,每个顶点为一棵独立的树,即一个独立的集合,边集a从题中读入,par数组初始值为本身标号;
  2. 操作——排序:将边集a按权值p从小到大排,自己写cmp函数:
    int cmp(const void*a, const void *b){
        return ((Node*)a)->price - ((Node*)b)->price;
    }

然后是这样调用的,将数组a前n个元素按cmp的规定排好序:

    qsort(a, n, sizeof(a[0]), cmp);
  1. 操作——加边(点):从小到大拿边,如果这条边的起点加边终点不在同一集合就合并(避圈加边法)
    for(int i = 0; i < n && nEdge != m - 1; i++){
        //判断当前这条边的两个端点是否属于同一棵树
        if(find(a[i].a) != find(a[i].b)){
            unite(a[i].a, a[i].b);//合并第i条边的起点和终点
            res += a[i].price;
            nEdge++;
        }
    }
  1. 跳出:自动跳出。注意:如果到最后生成树没达到n条边则说明这个图不存在最小生成树,因此在前面每加一个点都会让计数变量nedge自增一:
    if(nEdge < m-1) res= -1;
    return res;

好啦,今天就到这,我要出去耍啦~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值