当图变成了一棵树(纠结的生成树)
最小生成树
经典算法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
当图变成了一棵树(纠结的生成树)相关推荐
- 图11——判断图中是否为一棵树
编写算法,判断一个无向图是否是一颗树. [分析] 一个无向图G是一棵树的条件为:G必须是无回路的连通图或n-1条边的连通图,这里我们采用后者作为判断条件.例如下图所示: 上面的无向图就是一棵树,它有6 ...
- 51nod1325-两棵树的问题【最大权闭合图,网络流】
正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1325 题目大意 两棵树.要求选出一组权值和最大的点使得这两个点集在两棵树 ...
- 假设某专业有若干个班,每个班有若干学生,每个学生包含姓名和分数,这样构成一棵树,如图1所示。假设树中每个结点的name域均不相同,该树采用孩子兄弟链存储结构,其结点类型定义如下:
假设某专业有若干个班,每个班有若干学生,每个学生包含姓名和分数,这样构成一棵树,如图1所示.假设树中每个结点的name域均不相同,该树采用孩子兄弟链存储结构,其结点类型定义如下: typedef st ...
- 请画出五个具有五个结点的无向图,使之分别满足: (1) 是欧拉图但不是汉密尔顿图。 (2) 既是欧拉图也是汉密尔顿图。 (3) 是完全图K5。 (4) 是棵树。 (5) 是汉
请画出五个具有五个结点的无向图,使之分别满足: (1) 是欧拉图但不是汉密尔顿图. (2) 既是欧拉图也是汉密尔顿图.(3) 是完全图K5. (4) 是棵树. (5) 是汉密尔顿图但不是欧拉图 .
- 【数据结构】-图-判断一个无向图是否是一棵树
思路:判断一个无向图是否是一棵树,只需要判断该图是否是一个包含n个顶点的连通子图且边数为n-1,只要这两个条件都满足,那么就是一棵树. 因此我们可以采用深度遍历,若图连通,那么只要一次深度遍历就可以遍 ...
- 软路试--就像一棵树活着
余先生说:我们中的每一个,它应该成长就像一棵树.即使是现在,我们什么都不是,但就我希望你有树的种子,即使你是对土壤的一个中间步骤.您还可以吸收土壤中的养分,他们的成长起来.后,遥远的地方,人们就能看到 ...
- 一棵树的生成树有几颗_次小生成树(树剖,生成树)
生成树的概念: 在一个无向图中,设顶点数为\(n\),取其中\(n-1\)条边并使所有点相连,所得到的一棵树即为生成树. 最小生成树: 如果还没有接触过生成树的同学,欢迎戳->最小生成树详解 次 ...
- 一棵树,怎么就平衡了(图解AVL+实现)
什么是AVL树 大家好,我是bigsai,好久不见,甚是想念. 对于树这种数据结构,想必大家也已经不再陌生,我们简单回顾一下. 在树的种类中,通常分成二叉树和多叉树,我们熟悉的二叉树种类有二叉搜索(排 ...
- 数据结构-判断一棵树是否为二叉排序树
判断一棵树是否为二叉排序树 二叉排序树的性质:如果按照中序遍历的方式遍历二叉排序树的话,遍历的数字是呈递增趋势的.我们根据这个思路去判断是否为二叉排序树. 思路: ①建树 ②设立一个变量去记录当前已经 ...
- xgboost 一般多少棵树_大白话人工智能算法-第32节集成学习之通俗理解XGBoost原理和过程...
本节讲解XGBoost的原理~ 目录 1.回顾: 1.1 有监督学习中的相关概念 1.2 回归树概念 1.3 树的优点 2.怎么训练模型: 2.1 案例引入 2.2 XGBoost目标函数求解 3.X ...
最新文章
- 在ASP.Net中如何彻底杀死Excel进程
- Innosetup(pascal)标签控件label换行
- a - 数据结构实验之串一:kmp简单应用_串的两种模式匹配方式(BF/KMP算法)
- MySQL调优(二):数据类型和schema优化,MySQL8.0取消查询缓存的原因
- 第三方免费加固横向对比
- 2021 云原生开门红,金山云发布全新云原生全景图
- Linux下批量替换文件内容和文件名(转)
- linux : epoll详解
- 关于解决keil4和mdk共存后51不能使用go to definition Of 'XXXXXX'问题
- Selenium+Appium底层原理
- SonyZ2国行版L50t使用谷歌play服务安装谷歌四件套
- linux md5sum 文件夹,linux md5sum 的用法
- 测序技术的一些原理理解(sanger测序与illumina测序)
- java对文件进行md5加密,对文件进行 MD5 加密
- 【办公-excel】Excel批量翻译
- SiT5711:±5~±8ppb超高精度Stratum 3E恒温振荡器OCXO,1-60MHz
- AutoJs学习-实现2048游戏机
- 最全面的Python重点知识汇总,建议码住
- 地理信息系统-坐标系统
- 使用css将彩色图片转换为黑白图片
热门文章
- ReentrantReadWriteLock源码解读
- @Scope作用域代理的应用:@RefreshScope注解实现动态刷新配置的底层原理与实现
- leetcode-896-单调数列
- 企业网盘2016年度深度盘点,哪家才是NO.1?
- 了解 Nginx 主要应用场景
- RabbitMQ 实现RPC
- win7系统中任务计划程序的使用与查询
- 【Python】Webpy
- How to disable cursor positioning and text selection in an EditText? (Android)
- nodemon运行 提示错误:无法加载文件 C:\Users\gxf\AppData\Roaming\npm\nodemon.ps1,因为在此系统上禁止运行脚本。