最小生成树

经典算法Kruskal算法

int cmp(const node &c,const node &d)
{return c.z<d.z;
}int find(int x)           //路径压缩(没有按秩合并)的并查集
{if (fa[x]!=x)fa[x]=find(fa[x]);return fa[x];
}int unionn(int f1,int f2)
{fa[f1]=f2;
}int doit()
{int i,j=0;int tot=0;for (i=1;i<=m;i++){int r1=find(way[i].u);int r2=find(way[i].v);if (r1!=r2){tot+=way[i].z;unionn(r1,r2);j++;}if (j==n-1) break;}return tot;
}void Kruskal()
{sort(way+1,way+1+m,cmp);int size=doit();
}

这里不得不提一句什么叫

Kruskal重构树

例题
简单的代码讲解

Kruskal重构树可以拿来处理一些最小生成树的边权最值问题
形象的理解就是:
Kruskal连边时并不直接合并两个并查集
而是新建一个节点x
将两个点所在子树都连到x的儿子上

这样生成的树有一些十分优美的性质:

1.二叉树(好吧意义不大)
2.原树与新树两点间路径上边权(点权)的最大值相等
3.子节点的边权小于等于父亲节点(大根堆)
4.原树中两点之间路径上边权的最大值等于新树上两点的LCA的点权

看图理解一下吧

看一下性质的体现:
1.不用说了
2.原树上2—>5:2,新树上也是
3.不用说了
4.1—>6:4
确认满足性质

看一下Kruskal重构树的构建:

维护一个类似并查集的东西

其中有按秩合并和路径压缩
据说这样并查集的时间复杂度才有保证

树的记录方式:爸爸记录法(只记录父亲
没有必要把树上的边都连起来
结点深度只要调用一个记忆化搜索就好了
(代码还是很丑)

int cmp(const node &a,const node &b)
{return a.v<b.v;
}int find(int a)  //路径压缩
{if (fa[a]!=a) fa[a]=find(fa[a]);return fa[a];
}void kruskal()
{sort(e+1,e+1+m,cmp);int i,o=0;for (int i=1;i<=n;i++) fa[i]=i,size[i]=1;for (i=1;i<=m;i++){int f1=find(e[i].x);int f2=find(e[i].y);if (f1!=f2){if (size[f1]>size[f2]) swap(f1,f2);  //按秩合并 fa[f1]=f2;                           //并查集中的标志节点,f1连到f2上 size[f2]=max(size[f2],size[f1]+1);   //size并查集的深度 f[f1]=f2;                            //Kruskal重构树中的父节点 z[f1]=e[i].v;                        //Kruskal重构树中的结点值(就是原树中的边值) }}
}int getdep(int bh)
{if (deep[bh]) return deep[bh];if (!f[bh]) return deep[bh]=1;return deep[bh]=getdep(f[bh])+1;
}



言归正传,为了更好地理解最小生成树,
我们给出两条性质:

性质一:切割性质
假定所有的边权均不相同
设S为既非空集也非全集的V(点集)的子集,
边e是满足一个端点在S内,另一个端点不在S内的所有边中权值最小的边
则图G的所有生成树均包含e


性质二:回路性质
假定所有的边权均不同
设C是图G中的任意回路,边e是C上权值最大的边,
则图G的所有生成树不包含e

例1:
每对结点减的最小瓶颈路上的最大边长
解:
求出最小生成树之后:
一般来说,最朴素的用lca(n^2logn)
然而现在有了更好的做法:
用dfs把最小生成树变成有根树,同时计算f(u,v)
当新访问一个结点的时候,考虑所有访问过的老结点
更新f(x,u)=max(f(x,v),w(u,v)),其中v是u的父结点
复杂度O(n^2)

次小生成树

权值之和排在第二的生成树

最朴素的求法:像次短路一样,次小生成树和最小生成树不会完全一样,
我们枚举最小生成树上的边并删除,在剩下的边里做Kruskal,得到的生成树中权值最小的就是次小生成树
复杂度O(nmα(n,m))

还有一种更好的方法

枚举要加入哪条新边
在最小生成树上加上一条边u-v,图上会出现一条回路,我们需要删除一条边
所以删除的边一定在最小生成树中u-v的路径上
回路性质得,删除的一定是路上的一条最长边
所以我们像例一中一样,求出f(u,v)
剩下的部分只需要O(m)的时间(枚举所有m-n+1条边,O(1)求出新生成树的权值)
时间复杂度O(n^2)

有向最小生成树

给定一个有向带权图G和其中一个结点u,找到一个以u为根结点,权和最小的生成树
有向生成树(directed spanning tree)也叫树形图(arborescence)
是指一个类似树的有向图,满足如下条件

  • 恰好有一个入度为0的结点,称为根结点
  • 其他结点的入度均为一
  • 可以从根节点到达所有其他结点

朱-刘算法

首先是预处理:
删除自环判断根结点是否可以到达其他结点,如果不是,无解

算法主过程:
首先,给所有非根结点选择一条全最小的入边,
如果选出来的n-1条边构不成圈,则可以证明这些边形成了一个最小树形图
否则把每个圈缩成一个点,继续上述过程

缩圈之后,圈上的所有边都消失了,因此在最终答案的时候需要累加上这些边的权值
但是这样就有一个问题:
假设算法在某次迭代中,把圈C缩成了结点v
则下一次迭代的时候,给v选择的入边将与C中的入弧冲突

如图,圈中已经有了Y—>X,如果收缩之后我们又给X选了一条入边Z—>X
我们就要删除Y—>X(每个非根结点只有一个入度)
这等价于把弧Z—>X减小了Y—>X的权值

转载于:https://www.cnblogs.com/wutongtong3117/p/7673052.html

当图变成了一棵树(纠结的生成树)相关推荐

  1. 图11——判断图中是否为一棵树

    编写算法,判断一个无向图是否是一颗树. [分析] 一个无向图G是一棵树的条件为:G必须是无回路的连通图或n-1条边的连通图,这里我们采用后者作为判断条件.例如下图所示: 上面的无向图就是一棵树,它有6 ...

  2. 51nod1325-两棵树的问题【最大权闭合图,网络流】

    正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1325 题目大意 两棵树.要求选出一组权值和最大的点使得这两个点集在两棵树 ...

  3. 假设某专业有若干个班,每个班有若干学生,每个学生包含姓名和分数,这样构成一棵树,如图1所示。假设树中每个结点的name域均不相同,该树采用孩子兄弟链存储结构,其结点类型定义如下:

    假设某专业有若干个班,每个班有若干学生,每个学生包含姓名和分数,这样构成一棵树,如图1所示.假设树中每个结点的name域均不相同,该树采用孩子兄弟链存储结构,其结点类型定义如下: typedef st ...

  4. 请画出五个具有五个结点的无向图,使之分别满足: (1) 是欧拉图但不是汉密尔顿图。 (2) 既是欧拉图也是汉密尔顿图。 (3) 是完全图K5。 (4) 是棵树。 (5) 是汉

    请画出五个具有五个结点的无向图,使之分别满足: (1) 是欧拉图但不是汉密尔顿图. (2) 既是欧拉图也是汉密尔顿图.(3) 是完全图K5. (4) 是棵树. (5) 是汉密尔顿图但不是欧拉图 .

  5. 【数据结构】-图-判断一个无向图是否是一棵树

    思路:判断一个无向图是否是一棵树,只需要判断该图是否是一个包含n个顶点的连通子图且边数为n-1,只要这两个条件都满足,那么就是一棵树. 因此我们可以采用深度遍历,若图连通,那么只要一次深度遍历就可以遍 ...

  6. 软路试--就像一棵树活着

    余先生说:我们中的每一个,它应该成长就像一棵树.即使是现在,我们什么都不是,但就我希望你有树的种子,即使你是对土壤的一个中间步骤.您还可以吸收土壤中的养分,他们的成长起来.后,遥远的地方,人们就能看到 ...

  7. 一棵树的生成树有几颗_次小生成树(树剖,生成树)

    生成树的概念: 在一个无向图中,设顶点数为\(n\),取其中\(n-1\)条边并使所有点相连,所得到的一棵树即为生成树. 最小生成树: 如果还没有接触过生成树的同学,欢迎戳->最小生成树详解 次 ...

  8. 一棵树,怎么就平衡了(图解AVL+实现)

    什么是AVL树 大家好,我是bigsai,好久不见,甚是想念. 对于树这种数据结构,想必大家也已经不再陌生,我们简单回顾一下. 在树的种类中,通常分成二叉树和多叉树,我们熟悉的二叉树种类有二叉搜索(排 ...

  9. 数据结构-判断一棵树是否为二叉排序树

    判断一棵树是否为二叉排序树 二叉排序树的性质:如果按照中序遍历的方式遍历二叉排序树的话,遍历的数字是呈递增趋势的.我们根据这个思路去判断是否为二叉排序树. 思路: ①建树 ②设立一个变量去记录当前已经 ...

  10. xgboost 一般多少棵树_大白话人工智能算法-第32节集成学习之通俗理解XGBoost原理和过程...

    本节讲解XGBoost的原理~ 目录 1.回顾: 1.1 有监督学习中的相关概念 1.2 回归树概念 1.3 树的优点 2.怎么训练模型: 2.1 案例引入 2.2 XGBoost目标函数求解 3.X ...

最新文章

  1. 在ASP.Net中如何彻底杀死Excel进程
  2. Innosetup(pascal)标签控件label换行
  3. a - 数据结构实验之串一:kmp简单应用_串的两种模式匹配方式(BF/KMP算法)
  4. MySQL调优(二):数据类型和schema优化,MySQL8.0取消查询缓存的原因
  5. 第三方免费加固横向对比
  6. 2021 云原生开门红,金山云发布全新云原生全景图
  7. Linux下批量替换文件内容和文件名(转)
  8. linux : epoll详解
  9. 关于解决keil4和mdk共存后51不能使用go to definition Of 'XXXXXX'问题
  10. Selenium+Appium底层原理
  11. SonyZ2国行版L50t使用谷歌play服务安装谷歌四件套
  12. linux md5sum 文件夹,linux md5sum 的用法
  13. 测序技术的一些原理理解(sanger测序与illumina测序)
  14. java对文件进行md5加密,对文件进行 MD5 加密
  15. 【办公-excel】Excel批量翻译
  16. SiT5711:±5~±8ppb超高精度Stratum 3E恒温振荡器OCXO,1-60MHz
  17. AutoJs学习-实现2048游戏机
  18. 最全面的Python重点知识汇总,建议码住
  19. 地理信息系统-坐标系统
  20. 使用css将彩色图片转换为黑白图片

热门文章

  1. ReentrantReadWriteLock源码解读
  2. @Scope作用域代理的应用:@RefreshScope注解实现动态刷新配置的底层原理与实现
  3. leetcode-896-单调数列
  4. 企业网盘2016年度深度盘点,哪家才是NO.1?
  5. 了解 Nginx 主要应用场景
  6. RabbitMQ 实现RPC
  7. win7系统中任务计划程序的使用与查询
  8. 【Python】Webpy
  9. How to disable cursor positioning and text selection in an EditText? (Android)
  10. nodemon运行 提示错误:无法加载文件 C:\Users\gxf\AppData\Roaming\npm\nodemon.ps1,因为在此系统上禁止运行脚本。