首页 > 其他分享 >[学习笔记]Kruskal以及Kruskal重构树

[学习笔记]Kruskal以及Kruskal重构树

时间:2022-09-26 18:25:41浏览次数:95  
标签:重构 Kruskal 笔记 点权 include operatorname 边权

1. \(\operatorname{Kruskal}\) 最小生成树

本来觉得这个没必要写但是强迫症发作只能写了qwq
真实原因是我居然交了四发才过板子题可以说是人类之耻了
\(\operatorname{Kruskal}\) 算法需要先把边按照权值进行排序,用贪心的思想优先选取权值较小的边,并依次连接
若出现环则跳过此边(用并查集来判断是否存在环)继续搜,直到已经使用的边的数量比总点数少一即可
否则将两个不同的并查集合并
看个动图就能理解了(绿边表示已选,红边表示不可选)
image
考虑模板

P3366 【模板】最小生成树

点击查看代码
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#define WR WinterRain
#define int long long
using namespace std;
const int WR=1001000,mod=993244853;
struct Edge{
    int frm,to,val;
    bool operator<(const Edge&b)const{
        return val<b.val;
    }
}edge[WR<<1];
int n,m;
int tot,ans;
int fa[WR];
int read(){
	int s=0,w=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=(s<<1)+(s<<3)+ch-'0';
		ch=getchar();
	}
	return s*w;
}
void add(int u,int v,int val){
    edge[++tot].frm=u;
    edge[tot].to=v;
    edge[tot].val=val;
}
int getfa(int x){
    if(fa[x]==x) return x;
    return fa[x]=getfa(fa[x]);
}
signed main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++){
        int u=read(),v=read(),val=read();
        add(u,v,val);add(v,u,val);
    }
    sort(edge+1,edge+1+tot);
    for(int i=1;i<=tot;i++){
        int u=edge[i].frm,v=edge[i].to,val=edge[i].val;
        int fau=getfa(u),fav=getfa(v);
        if(fau==fav) continue;
        fa[fau]=fav;
        ans+=val;
    }
    for(int i=2;i<=n;i++){
        if(getfa(i)!=fa[1]){
            printf("orz\n");
            return 0;
        }
    }
    printf("%lld\n",ans);
	return 0;
}

然后我们考虑

2. \(\operatorname{Kruskal}\) 重构树

考虑下图

image

显然地,这张图的最小生成树是

image

其实建重构树的过程差不多,一共两步循环操作

  1. 将所有边按边权从小到大排序
  2. 每次找最小的一条边,如果条边相连的两个点在同一个集合中,那么就跳过,否则就将这两个点的祖先都连到一个虚点上去,让这个虚点的点权等于这条边的边权

所以理论上最后建出来的的重构树是这样的:

image

这棵树有很多独特的性质

  1. 原本最小生成树上的点在重构树里都是叶节点
  2. 从任何一个点往根上引一条路径,这条路径经过的点的点权单调不降(最大生成树单调不升)
  3. 任意两点之间路径的最大边权就是他们的 \(\operatorname{LCA}\) 的点权

标签:重构,Kruskal,笔记,点权,include,operatorname,边权
From: https://www.cnblogs.com/WintersRain/p/16731520.html

相关文章

  • 【学习笔记】初始JQuery
    初始JQuery 了解JQueryjQuery和JavaScript的关系:jQuery相当于一个库,里面有大量的JavaScript函数和Java中的工具类差不多。 获取jQuery 官网下载[jquery.co......
  • Flink笔记
    高可用(HA):直白来说就是系统不会因为某台机器,或某个实例挂了,就不能提供服务了。高可用需要做到分布式、负载均衡、自动侦查、自动切换、自动恢复等。高吞吐:单位时间内,能......
  • Jmeter学习笔记
    安装部署直接去官网下载最新版jmeter,解压到任意目录官网地址:https://jmeter.apache.org/download_jmeter.cgi安装JDK8+(这里不再介绍步骤)配置jmeter环境变量可以在运......
  • RocketMQ性能优化【实战笔记】
    转发:https://cloud.tencent.com/developer/article/1496414目录一、系统优化1.最大文件数2.系统参数调整二、RocketMQ性能调优1.开启异步刷盘2.开启堆外内存设置3......
  • TypeScript学习笔记(三)—— 编译选项、声明文件
    一、编译选项与配置文件自动编译文件编译文件时,使用-w指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。示例:tscxxx.ts-w......
  • 自然语言处理NLP(学习笔记)
       NLP的概念自然语言处理,英文NaturalLanguageProcessing,简写NLP。NLP这个概念本身过于庞大,可以把它分成“自然语言”和“处理”两部分。自然语言先来看......
  • 线段树学习笔记(基础&进阶)(一) | P3372 【模板】线段树 1 题解
    什么是线段树线段树是一棵二叉树,每个结点存储需维护的信息,一般用于处理区间最值、区间和等问题。线段树的用处对编号连续的一些点进行修改或者统计操作,修改和统计的复杂......
  • C++自学笔记
    初始化pA(){p=0;cout<<"A::A()"<<endl;}初始化列表InitializerlistA():p(0){cout<<"A::A()"<<endl;}      初始化vs赋值   赋值=默认初始化+......
  • axios学习笔记
    1axios的理解和使用1.1axios是什么前端最流行的ajax请求库react/vue官方都推荐使用axios发ajax请求文档地址1.2axios特点基于xhr+promise的异步ajax请求浏览......
  • js红宝书学习笔记(一)引用类型
    一.引用类型  ECMAScript中,引用类型是一种数据结构称之为对象定义,,引用对象不同于传统面向对象语言所支持的类和接口等基本结构 创建Object实例的两种方式:new操......