首页 > 其他分享 >边分治 学习笔记

边分治 学习笔记

时间:2022-12-24 09:00:42浏览次数:56  
标签:cur int void 分治 笔记 学习 add las

边分治 学习笔记

就普遍理性而论,边分治能做的点分治也能做,可是难度…

参考博客:边分治讲解

前置:多叉树转二叉树

也叫三度化。

边分治在二叉树上表现得很优秀,是 \(O(nlogn)\),而在菊花图上,因为分割不均等等问题会被卡到 \(O(n^2)\)。所以,多叉树转二叉树在此显得尤为重要。

法一

算法流程:

  1. 若一个点有两个以上的儿子,新建两个点,并向其连边(边权为 \(0\))。
  2. 然后该点原来的儿子暂且归为这两个儿子,重复第一步。
  3. 直到他只有有两个及以下的儿子,向所有儿子连边。

Tip:均分时可以按照奇偶分类。

void pre(int u, int f) {//无向图预处理求父亲
	fa[u] = f;
	for (int v : g[u])
		if (v != f)
			pre(v, u);
}
void reBuild() {
	pre(1, 0);
	for (int u = 1; u <= n; ++u) {
		if ((int)g[u].size() - (fa[u] != 0) <= 2) {//真实儿子数量
			for(int i = 0; i < (int)g[u].size(); ++i)
				if (g[u][i] != fa[u])
					add(u, g[u][i], w[u][i]), 
					add(g[u][i], u, w[u][i]);
		}
		else{
			int ls = ++n,rs = ++n;
			val[ls] = val[rs] = val[u];
			add(u, ls, 0); add(ls, u, 0);
             add(u, rs, 0); add(rs, u, 0);
			for (int i = 0;i < (int)g[u].size(); ++i) {
				if (g[u][i] == fa[u]) swap(ls, rs);
				else g[i & 1 ? ls : rs].push_back(g[u][i]);
			}
		}
	}
}

注意:这种方法需要预处理出父亲信息,并在访问到时特殊判断。详见代码中的 pre 函数。

法二

算法流程:

  1. 对于一个点 \(x\),记录一个 \(last\)(初始为 \(x\))。
  2. 将 \(last\) 向下一个子节点连边(初始时为第一个)。
  3. 新建节点 \(p\),将 \(last\) 向 \(p\) 连边(边权为 \(0\))。
  4. 将 \(last\) 改为 \(p\)。重复步骤 \(2\),直到建完所有儿子。
void reBuild(int u, int fa) {
	int las = u, p, lim = g[u].size() - (fa != 0);
	for (int i = 0; i < (int)g[u][i]; ++i) {
		int v = g[u][i];
		if(v != fa) {
			add(las, v, d[u][i]);
			add(v, las, d[u][i]);
			if (i < lim-1) {
				p = ++n;
				add(las, p, 0);
				add(p, las, 0);
				las = p;
			}
		}
		else ++lim;
	}
	for (int v : g[u])
		if(v != fa)
			reBuild(v,u);
}

提供 @yanchengzhi 大佬的写法

void dfs1(int u, int from) {
	bool flag = 0;
	for(edge1 i : e1[u]) {
		int v = i.v; ll w = i.w;
		if(v == from) continue;
		cur++;
		add(cur, v, w);
		add(v, cur, w);
		if(flag) {
			add(cur, cur - 1, 0);
			add(cur - 1, cur, 0);
		}
		else {
			add(cur, u, 0);
			add(u, cur, 0);
		}
		flag = 1;
	}
	for(edge1 i : e1[u]) {
		int v = i.v;
		if(v == from) continue;
		dfs1(v, u);
	}
}

时空复杂度

可以证明,上述办法时空均为 \(O(n)\),不过空间需要开大一点,一般为 \(2\) 倍左右,可适当开大(稳一点建议开 \(4\) 倍)。

边分治

算法流程

类似于点分治的思想,边分治也是对于每一个点求出其两端的最大子树大小,并取最小的作为分治中心。

void getG(int u, int e, int all) {
	sz[u] = 1;
	for (int i = fi[u]; i; i = nxt[i]) 
		if ((i >> 1) != e && !vis[i >> 1]) {
			int v = to[i];
			getG(v, i >> 1, all);
			sz[u] += sz[v];
		}
	if (e) maxp[e] = max(sz[u], all - sz[u]);
	if (maxp[e] < maxp[G])
		G = e;
}

解释:\(e\) 是进入该点 \(u\) 时访问的边,\(all\) 是当前分治区域的点数。

细节注意

  • 建图时一般是要在新图上开双向边。
  • 建图时下标从 \(2\) 开始,因为这样可以快速访问一条边的两个端点,具体而言,一条边 \(i\) 的两个端点分别为:\(to[i],to[i\oplus 1]\)(其中 \(\oplus\) 代表按位异或)。
  • 建图时,某些边权值应该设成 \(0\),或者时无穷小之类的不会影响答案的值。

标签:cur,int,void,分治,笔记,学习,add,las
From: https://www.cnblogs.com/lazytag/p/17001985.html

相关文章

  • 机器学习---花卉识别
    一、选题的背景因为我以前的专业是林学,平时需要上山出外业经常遇到一些不认识的花,那时候问老师或者自身学习记住了不少,但是渐渐的也忘记了,所以我选了花卉识别作为题目。......
  • 机器学习——机动车图片识别
    一、选题的背景随着城市化建设不断发展,我国对交通建设的需求也不断增长,成为了世界上在交通领域基础设施建设最快的国家之一,但车辆管控问题、道路交通问题、车辆违章问题......
  • 达梦基础学习知识
    1.达梦基础适配知识2.达梦DQL和DML运行3.达梦数据库配置参数 ......
  • 机器学习——自动生成古诗词
    自动生成古诗词一、选题背景自动生成古诗词的初衷是想培养中小学生的传统文化,感受中华上下五千年的古诗词魅力,并培养他们的作词能力,陶冶情操二、机器学习的实现步骤从......
  • 寒假学习内容
    年前:重新学习JavaWeb并做好笔记年后:SSM框架:简化web开发的经典框架SpringBoot:简化Spring开发的框架SpringCloud:微服务开发的解决方案容器技术:Docker 在学习这些之......
  • 废物利用,笔记本显示器拆机使用
    我自己有个老笔记本已经坏了,本来打算扔掉,忽然有个想法,可以吧显示器拆下来使用啊。于是上网查资料,还真可以。特此记录,方便以后查找。下面是步骤。把笔记本显示器拆下来。......
  • 机器学习——鞋类别识别
    机器学习——鞋类别识别一、选题背景随着计算机硬件的不断发展,人工智能再次走进研究人员的实现,通过构造一定智能的人工系统,让机器去完成以往需要人类智力才能胜任的......
  • # Win10为知笔记Docker镜像部署 -v /wiz/storage问题解决
    Win10为知笔记Docker镜像部署-v/wiz/storage问题解决用了很长一段时间的为知笔记,客户端体验还行,服务端笔记同步体验不佳。准备用Docker自己搭一个服务端。环境:操作......
  • FFT入门——学习笔记
    FFT入门给一个非常好的入门视频:快速傅里叶变换复数与单位根定义:\(i^2=-1\)为虚数单位,我们称形如\(a+bi(a,b\inR)\)的数为复数。我们可以用复数在复平面上表示点\((0,......
  • 机器学习——景观识别
    一、选题背景:景观识别是一种人工智能技术,旨在通过自然场景的图像或视频来识别和分类不同的景观类型。这种技术可以用于多种应用场景,如旅游、地理信息系统、环境监测等。......