备战蓝桥杯---树学初步1

news/2024/7/15 17:29:19 标签: 深度优先, 算法, c++, 蓝桥杯, 数据结构, 图论, DFS序

LCA(最近公共祖先)

定义:有根树的两个节点u,v,他们的LCA是一个节点x,其中x是他们的公共祖先并且X的深度尽可能大。

法1---Tarjan算法

核心:DFS+并查集

在并查集中建立仅有u的集合,设该集合祖先为u,对于他的每一个孩子v:dfs(v)

合并v到父节点u的集合,设置u为已遍历。

有点抽象,来看看图例吧:

首先,一开始每一个点的fa都是自己,然后遍历到11,它没有儿子,设置11为已遍历并指向5,然后到12,此时若有11与12的询问就是11的fa,标记12并到5,5指2并标记,依次类推即可

注意,这要把所有询问提前记录下来(即离线操作)

下面是模板代码:

#include<bits/stdc++.h>
using namespace std;
int fa[100000];
vector<int> a[100000];
int que[1000][1000];
bool vis[100000];
int find(int x){
	if(x==fa[x]) return x;
	return fa[x]=find(fa[x]);
}
void merge(int x,int y){
	x=find(x);
	y=find(y);
	fa[x]=y;
}
void dfs(int x,int fa){
	for(int i=0;i<a[x].size();i++){
		int y=a[x][i];
		dfs(y,x);
		merge(y,x);
	}
	vis[x]=1;
	for(int i=1;i<=n;i++){
		if(vis[i]&&que[x][i]){
			int tmp=find(i);
			cnt[tmp]+=que[x][i];
			que[x][i]=que[i][x]=0;
		}
	}
}

法2--通过DFS序转化成RMQ问题

对有根树DFS,按照遍历顺序记录2*N-1的序列即欧拉序列

我们发现两个数(u,v)(前面的先出现)的LCA就是最后一次出现的u和第一次出现的v中间的数就是从u--v的路径,而其中深度最低(包含自己)的就是其LCA。

因此我们求一个min即可,其中我们为了方便可以从第一次出现的u开始(其子树不影响)

怎么求RMQ?

1.线段树。

2.ST。

线段树大家都知道,那么就看一下ST吧

In a word,ST就是DP+倍增

我们用f[i][j]表示[i,i+2^j-1]的min,f[i][0]=a[i],因此,f[i][j]=min(f[i][j-1],f[i+2^(j-1),][j-1])

当我们要查询时,对于[10,20],我们可以先得到[10,18]的min与[19,20](根据2进制看)

我们也可以[10,18]以及[12,20]。

下面是模板代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int b[N],dp[N][N];
void rmq_st(int n){
	for(int i=1;i<=n;i++) dp[i][0]=b[i];
	int m=(int)(log(1.0*n)/log(2.0));
	for(int j=1;j<=m;j++){
		int t=n-(1<<j)+1;
		for(int i=1;i<=t;i++){
			dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
		}
	}
}
int rmp_find(int l,int r){
	int k=(int)(log(1.0*(r-l+1))/log(2.0));
	return min(dp[l][k],dp[r-(1<<k)+1][k]);
}

接下来我们看看如何编号。

我们用DFN序编号即可以(直接按照深度存的话对于一个深度可能有很多对应)

下面是实现代码:

void dfs(int x,int fa){
	int tmp=++num;
	b[++cnt]=tmp;//以DFS代替的欧拉序 
	f[tmp]=x;//实现从DFS序到真实点的映射 
	first[x]=cnt;//记录x第一次出现的位置 
	for(int i=head[x];i!=-1;i=edge[i].next){
		int v=edge[i].dian;
		if(v==fa) continue;
		dfs(v,x);
		b[++cnt]=tmp;
	}
}
int LCA(int a,int b){
	if(first[a]>first[b]) swap(a,b);
	int k=rmq_find(first[a],first[b]);
	return f[k];
}

下面介绍一下如何求两个点的距离算是应用吧:

每一个点到根的距离-2*LCA到根的距离。

下面介绍介绍常见的3种“dfs序”

欧拉序:每经过一点记录一次的序列
DFS序:记录进栈与出栈的序列。
DFN序:只记录进栈的序列。

对于这个图:

欧拉序:12552.....DFS序:1255662379.。。。DFN序(时间戳):12563....

对于时间戳:

125637948,我们记录一下每一个子树的最大时间(即最后进栈),我们发现对于256,379,任何一个子树在其中都是连着并不重复出现的,而当我们知道一个子树的最大时间就知道了对应的区间。

这有什么用呢?

在树上1.修改x变成Y,2.查以x为根的子树的权值和。

这就转化成了区间和的问题,对DFN序再用树状数组维护即可。

我们来个应用吧:

我们先按DFN,我们发现一个点要么跟父亲一样,要么是一个从来没有出现的点,这个就是合法的,于是我们令dp[i][j]表示走到i时用了j种颜色的方案数,易得状态转移方程:

dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(k-j+1).

下面是AC代码:

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
int n,y,k,x;
long long dp[400][400];
int main(){
    cin>>n>>k;
    dp[0][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=k;j++){
            dp[i][j]=(dp[i-1][j]+dp[i-1][j-1]*(k-j+1))%mod;
        }
    }
    long long ans=0;
    for(int i=1;i<=k;i++) ans=(ans+dp[n][i])%mod;
    cout<<ans;
}


http://www.niftyadmin.cn/n/5460306.html

相关文章

Codigger开发者篇:开启全新的开发体验(二)

在数字化浪潮中&#xff0c;开发者们始终在追求更加高效、便捷的开发工具与环境。Codigger&#xff0c;作为新一代开发、运营、使用私人应用的分布式操作系统&#xff0c;正是为这些追求者们量身打造的利器&#xff0c;Codigger是一个跨时代的颠覆式的创新。今天&#xff0c;我…

android PKMS服务

前面我们介绍过Android AMS服务&#xff0c;今天我们看一下PKMS(PackageManagerService)服务&#xff0c;PKMS也是android系统中核心服务之一&#xff0c;负责应用程序的安装&#xff0c;卸载&#xff0c;信息查询等工作。 PKMS的启动 首先启动创建PKMS: private void start…

命名空间【C++】(超详细)

文章目录 命名空间的概念命名空间的定义命名空间定义的位置作用域每一个命名空间都是一个独立的域作用域符&#xff1a;&#xff1a; 编译器找一个变量/函数等的定义&#xff0c;寻找域的顺序为什么要有命名空间&#xff1f;1.解决库与程序员定义的同名的重定义问题2.解决程序员…

[flask]请求全局钩子

flask从入门到精通之钩子、异常、context、jinjia模板、过滤器 - 异步非阻塞 - 博客园 (cnblogs.com) 参考的这个博客&#xff0c;但有一个需要注意的是&#xff0c;最新版本的flask不知道是不是更新了还是怎么了&#xff0c;他的before_first_request不见了&#xff0c;如果继…

WEPE系统安装纯净版window11教程(包含pe内系统安装方法)

目录 一.安装u盘启动盘 1.1制作安装系统引导盘 1.2下载保存windows镜像 1.3根据自己电脑品牌查询进入BIOS设置的方法 1.4我们成功进入了PE 二.重装系统 2.1遇到问题 2.2重新来到这个界面 三.PE中基本软件的作用 四.学习声明 今天不敲代码&#xff0c;今天来讲讲We P…

Java-常见面试题收集(七)

十四 MySQL 1 MySQL 支持的存储引擎 MySQL 支持多种存储引擎&#xff0c;常见的有2种&#xff0c;你可以通过 show engines 命令来查看 MySQL 支持的所有存储引擎。MySQL 当前默认的存储引擎是 InnoDB。并且&#xff0c;所有的存储引擎中只有 InnoDB 是事务性存储引擎&#xf…

服务器大请求体问题定位

背景 整个系统,分位微服务A、微服务B,A在调用B的过程中,报400BadRequest,问题定位到修复后,如何发送一个同样的请求进行验证 解决过程 1、查询A服务的日志,发现在调用B的过程中报错400BadRequest,并且请求体非常大300多KB 2、查看B服务的日志,发现请求没有进来 3、发…

vulhub打靶记录——driftingbox

文章目录 主机发现端口扫描目录扫描爆破子域名提权总结 主机发现 使用nmap扫描局域网内存活的主机&#xff0c;命令如下&#xff1a; nmap -sP 192.168.56.0/24192.168.56.1&#xff1a;主机IP&#xff1b;192.168.56.100&#xff1a;DHCP服务器IP&#xff1b;192.168.56.101…