树上差分-LCA

news2024/9/29 15:23:55

树上差分

  • 算法分析:
  • 练习例题

差分的基本思想详情见博客(一维、二维差分):
https://blog.csdn.net/weixin_45629285/article/details/111146240

算法分析:

面向的对象可以是树上的结点,也可以是树上的边
结点表述方式:
问题:
给定一棵有N个点的树,所有节点的权值初始时都为0。
有K次操作,每次指定两个点s,t,将s到t路径上所有点的权值都+c,求最后树上每个结点的权值。
在这里插入图片描述

求解思路:
对于每一次修改s,t,将s,t的权值+c;
将LCA(s,t)和father[LCA(s,t)]的权值-c;
K次操作后每个结点最终被覆盖的次数(最终的权值)就是这个点所在子树的权值和。

在这里插入图片描述

边表述方式:
问题:
给定一棵有N个点的树,或者为有N-1条边将任意两个点通过路径连接起来的无向图,所有边的权值初始时都为0。
有K次操作,每次指定两个点s,t,将s到t路径上所有边的权值都+c,求最后树上每个边的权值。
在这里插入图片描述

求解思路:
对于每一次修改结点s,t,将s,t的权值+c;
将LCA(s,t)的权值-2*c;
K次操作后每个边最终被覆盖的次数(最终的权值)就是这个边下面的结点所在子树的权值和。

在这里插入图片描述
注意,两种方式的表示方法的求解思路有一点小的不同,但是我们只要保证一个思想,就是需要增加的才增加,不需要改变的就要减去
其中求LCA有三种方法:向上标记法、倍增法和tarjan离线算法,具体参考博客:https://blog.csdn.net/m0_58642116/article/details/128550161?spm=1001.2014.3001.5501

练习例题

链接:
https://www.acwing.com/problem/content/description/354/
分析:
1.主要边就构成了一棵树,附加边其实就是非树边,读题的时候就要能读出来,转化一下意思
2.一个附加边如果与一些主要边组成了环,这个环上的所有主要边砍断的同时也需要砍断这个附加边,也就相当于这些主要边砍断树的可能性都加一;如果主要边没有跟附加边组成环,那直接砍断这个主要边就能使得图不连通;但是如果主要边与多个附加边组成了环,砍断了当前主要边,再砍一个附加边没法使图不连通
3.最终也就是转化为了树上两个结点之间路径的问题,转化为树上差分问题
任意一个附加边,将附加边两端结点(s,t)间的树边的权值都加一,也就是s权值+1,t权值+1,LCA(s,t)-2;
AC代码:

#include<iostream>
#include<vector>
#include<queue>
#include<string.h>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m,u,v,ans=0;
const int N=100005;
vector<int>tr[N]; 
int depth[N],fa[N][17];
int wei[N];  //树中每个结点的权值 

void bfs(int s)
{
	queue<int>que;
	memset(depth,INF,sizeof(depth));
	que.push(s);
	depth[0]=0;depth[1]=1;
	while(!que.empty())
	{
		int u=que.front();
		que.pop();
		
		for(int i=0;i<tr[u].size();i++)
		{
			int v=tr[u][i];
			if(depth[v]==INF)
			{
				depth[v]=depth[u]+1;
				que.push(v);
				
				fa[v][0]=u;
				for(int k=1;k<=16;k++)
				{
					fa[v][k]=fa[fa[v][k-1]][k-1]; 
				} 
			}
		}
	}
}
int LCA(int x,int y)
{
	if(depth[x]<depth[y]) swap(x,y);
	for(int k=16;k>=0;k--)
	{
		if(depth[fa[x][k]]>=depth[y])
		{
			x=fa[x][k];
		}
	}
	if(x==y) return x;
	for(int k=16;k>=0;k--)
	{
		if(fa[x][k]!=fa[y][k])
		{
			x=fa[x][k];
			y=fa[y][k];
		}
	}
	return fa[x][0];
} 

int dfs(int s,int fa)
{
	//以s为根节点的子树的权值 
	int num=0;
	for(int i=0;i<tr[s].size();i++)
	{
		if(tr[s][i]==fa) continue;
		num+=dfs(tr[s][i],s);
	}
	
	//再加上边下面的这个结点的权值(当前子树根节点权值) 
	num+=wei[s];
	
	if(s==1)  return num;  //跟结点上面的那个边不存在,直接返回 
	
	if(num==0)  ans+=m;   //当前主要边(树边)没有与任何附加边(非树边)组成环,直接砍断就能使得图分成两半,附加边就随便砍哪条都行 
	else if(num==1) ans+=1;   //当前主要边与一条 附加边组成环,要想使得图不连通砍断这个边的同时还要砍断那条附加边 
	//num>=2时,主要边与多个附加边组成了环,砍断了当前主要边,再砍一个附加边没法使图不连通 
	return num;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<n;i++)
	{
		cin>>u>>v;
		tr[u].push_back(v);
		tr[v].push_back(u);
	}
	bfs(1);  //倍增法初始化depth、fa数组
	
	//直接输入遍历非树边(附加边)
	for(int i=0;i<m;i++)
	{
		cin>>u>>v;
		int lca=LCA(u,v);
	//	cout<<lca<<endl;
		wei[u]+=1;  //差分求权值
		wei[v]+=1;
		wei[lca]-=2;
	} 
	//遍历整棵树差分法求每条边的权值,并对树边进行讨论求方法数
	dfs(1,-1);
	cout<<ans<<endl;
	return 0;
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springmvc 文件上传请求转换为MultipartFile的过程

前言: 最近在研究文件上传的问题,所以就写下这个博客,让大家都知道从流转换为MutipartFile的过程,不然你就知道在方法中使用,而不知道是怎么样处理的,是不行的 从DiaspatherServlet说起: 别问为啥,去了解tomcat和servlet的关系,我后面会 写这篇博客的 servlet的生命周期 ini…

[ 数据结构 ] 查找算法--------线性、二分、插值、斐波那契查找

0 前言 查找算法有4种: 线性查找 二分查找/折半查找 插值查找 斐波那契查找 1 线性查找 思路:线性遍历数组元素,与目标值比较,相同则返回下标 /**** param arr 给定数组* param value 目标元素值* return 返回目标元素的下标,没找到返回-1*/public static int search(…

63.Python 调用类的属性和方法

63.调用类的属性和方法 文章目录63.调用类的属性和方法1. 调用属性的语法2.调用类的方法3.总结1. 调用属性的语法 我们根据类创建了一张奥迪A6的小汽车。根据汽车流水线呢&#xff0c;汽车生产完之后&#xff0c;需要移交给检查部门检查车辆的外观、颜色(属性)等是否与图纸一致…

JavaEE高阶---SpringBoot 统一功能处理

一&#xff1a;什么是SpringBoot 统⼀功能处理 SpringBoot统一功能处理是AOP的实战环节。我们主要学习三方面内容&#xff1a; 统一用户登录权限验证&#xff1b;统一数据格式返回&#xff1b;统一异常处理。 二&#xff1a;统一用户登录权限验证 Spring 中提供了具体的实现…

Scala 集合常用函数

文章目录集合常用函数一、基本属性和常用操作1、常用方法2、案例示例二、衍生集合1、衍生集合常用方法操作2、案例示例三、集合简单计算函数1、常用计算操作2、案例示例四、集合计算高级函数1、语义说明2、案例示例集合常用函数 一、基本属性和常用操作 1、常用方法 (1) 获取…

Release库与Debug库混用导致释放堆内存时产生异常的详细分析

目录 1、问题描述 2、使用Windbg启动Debug版本的exe程序进行分析 3、进一步分析 4、问题复盘 5、为什么Debug库与Release库混用可能会出异常&#xff1f; 6、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;ht…

DM8:dexpdimp-逻辑导出--逻辑导入

DM8:dexp&dimp-逻辑导出--逻辑导入1 dexp逻辑导出dmp文件1.1 全库导出命令附加的参数信息1.2 导出用户所拥有权限的数据库对象-命令附加的参数信息1.3 导出用户所拥有权限的数据库对象-命令附加的参数信息2 dimp--逻辑导入dmp文件2.1 全库导入dmp数据文件-命令附加的参数信…

人体姿态估计-论文精读--DeepPose: Human Pose Estimation via Deep Neural Networks

图 1. 除了关节的极端变异性外&#xff0c;许多关节几乎不可见。我们能猜测左图中右臂的位置&#xff0c;因为我们看到了姿势的其余部分&#xff0c;并预测了这个人的运动或活动。同样&#xff0c;右边的人的左半身也根本看不见。这些都是需要进行整体推理的例子。我们相信DNNs…

php处理支付宝应用网关给接口发送的post参数

php如何接收支付宝应用网关发送的POST请求方式,参数又是GET请求的数据格式配置支付宝应用网关如何接收支付宝异步通知(应用网关接收请求)将&连接的参数分割成数组实例&#xff1a;难点配置支付宝应用网关 首先要在服务器上写一个接口,然后将接口的访问地址设置在支付宝应用…

手把手教Arthas,不再怕排查线上问题了

Arthas是alibaba开源的java诊断工具&#xff0c;支持jdk6&#xff0c;采用命令行交互模式&#xff0c;可以防败的定位和诊断线上的程序运行问题。官方文档&#xff1a;https://arthas.aliyun.com/doc/一、Arthas使用场景是否有一个全局视角来查看系统的运行状况&#xff1f;为什…

六种方式,教你在SpringBoot初始化时搞点事情!

前言 在实际工作中总是需要在项目启动时做一些初始化的操作&#xff0c;比如初始化线程池、提前加载好加密证书....... 那么经典问题来了&#xff0c;这也是面试官经常会问到的一个问题&#xff1a;有哪些手段在Spring Boot 项目启动的时候做一些事情&#xff1f; 方法有很多…

卷积层里的多输入多输出通道、池化层

多输入多通道每个通道都有一个卷积核&#xff0c;结果是所有通道卷积结果的和。无论有多少输入通道&#xff0c;到目前为止我们只用到单输出通道。可以有多个三维卷积核&#xff0c;每个核生成一个输出通道。输出通道数是卷积层的超参数。每个输入通道有独立的二维卷积核&#…

为什么JavaScript这么难学啊?

前言 觉得Js难其实是很正常的&#xff0c;首先这证明你在某些知识点上没有理解透彻&#xff0c;JS挺多的知识点点其实是比较抽象的&#xff0c;比如闭包、原型和原型链等&#xff0c;其次便是不会变通运用&#xff0c;这主要是敲代码熟练度的问题&#xff0c;所以我针对你这种…

架构运维篇(六):MySQL 8.0启用BinLog 支持

上一篇&#xff1a;架构运维篇&#xff08;五&#xff09;&#xff1a;Centos7/Linux中安装RocketMQ 最新线上的项目终于到多个数据执行的问题&#xff0c;找了团队DBA发现云上的MySQL 默认是没有启用BinLog支持。 小编研究了一下很简单&#xff0c;不过中间也遇到一些坑可以给…

结构重参数化(Structural Re-Parameters)PipLine

文章目录BASICSstrcutural Inception算法思想算法核心算法架构Re-Parameter四部曲&#xff1a;ACNetACNet原理ACNet分析涨点原因推理阶段融合机制Re-Parameter四部曲&#xff1a;RepVGGRepVGG原理RepVGG分析RepVGG BlockStructural Re-Parameters融合conv2d和BN融合1x1conv转换…

【一文讲通】样本不均衡问题解决--下

1欠采样、过采样欠采样&#xff1a;减少多数类的数量&#xff08;如随机欠采样、NearMiss、ENN&#xff09;。过采样&#xff1a;尽量多地增加少数类的的样本数量&#xff08;如随机过采样、以及2.1.2数据增强方法&#xff09;&#xff0c;以达到类别间数目均衡。还可结合两者做…

地址解析协议ARP

目录地址解析协议ARP1、流程2、动态与静态的区别3、ARP协议适用范围地址解析协议ARP 如何从IP地址找出其对应的MAC地址&#xff1f; 1、流程 ARP高速缓存表 当主机B要给主机C发送数据包时&#xff0c;会首先在自己的ARP高速缓存表中查找主机C的IP地址所对应的MAC地址&#xf…

Linux常用命令——lsblk命令

在线Linux命令查询工具 lsblk 列出块设备信息 补充说明 lsblk命令用于列出所有可用块设备的信息&#xff0c;而且还能显示他们之间的依赖关系&#xff0c;但是它不会列出RAM盘的信息。块设备有硬盘&#xff0c;闪存盘&#xff0c;cd-ROM等等。lsblk命令包含在util-linux-ng…

ES报文辅助生成工具-JavaFX

此程序为基于 Java8 开发的 JavaFX Maven 工程&#xff0c;是 Java 组装ElasticSearch请求报文工具的辅助 Java 代码生成工具&#xff0c;方便开发者快速编写代码。现学现用&#xff0c;写得不好。 工具界面 代码 pom.xml <project xmlns"http://maven.apache.org/P…

Android:URLEncoder空格被转码为“+”号

Android前段和后端接口交互时&#xff0c;经常会遇到特殊字符&#xff0c;比如表情、特殊标点等&#xff0c;这样在Url中是无法识别的&#xff0c;需要进行转码&#xff0c;后端进行解码交互。 但当使用URLEncoder时&#xff0c;会发现字符串中的空格被转换成“”号&#xff0…