『OI笔记』次小生成树
前置芝士
- 一点点图论芝士
- Kruskal(或者你用Prim也行),用来求最小生成树
定义
定义就是字面意思,无需解释。
思路
先将输入的图的最小生成树求出来,再枚举没有增加过的边,将他们加入到最小生成树当中去。新增一条边之后,我们就可以得到一个基环树。 接下来,我们在这棵基环树上找到环,并删除环上最长的边,这是我们就可以得到一颗新的树。通过枚举每一颗新的树,找到这些树中的最小的树,这就是最终的次小生成树了。
具体步骤
¶Step 1
首先当然是要跑一遍kruskal拉! :idea:
¶Step 2
我们要解决一个问题:那就是如何快速地找到环上最大的边?当然是预处理了。所以,我们可以在Kruskal(Prim党自便)求最小生成树的时候顺便存一下两点之间的最长路径。 怎么存?由于Kruskal和Prim的算法原理有些不同,所以Prim的同学可以先退场了。由于我们只是要求两个点所在的环上的最长边,所以就等于在这两个点合并前时候他们所在的子集的最长边。 所以,我们就要储存好该集合(树)下所有的点。这个不难,用vector就可以了。还有,因为kruskal在开始加边前经过sort,所以在后面出现的边的边权一定大于前面出现的,所以直接等于就可以了。转存的代码如下:
1 |
|
1 |
|
注意,以上代码是在kruskal里边的!!
¶Step 3
最后统计答案的时候,新建一个ans,原来最小生成树的权值和就用sum把。我们按照思路上的,枚举每一个不再最小生成树中的边,然后对ans进行更新就OK了!
1 |
|
例题及代码
POJ 1679 The Unique MST POJ不给用万能头文件大大的差评!XPINXPINXPINXPINXPINXPINXPIN
1 |
|
终 THE END
『OI笔记』次小生成树
https://学习.fun/oi-note/sub-small_spanning_tree/