当前位置: 首页 > news >正文

算法提升-树上问题之(dfs序)

今天带来分享的是关于树中dfs序的相关内容,简而言之,通过dfs序可以将树上的问题转化为数组的问题,即通过dfn数组将进行标号。同时通过idx数组将节点的信息存入dfn中。用来处理某些子树问题很方便

核心代码部分

接下来通过几道例题来帮助大家更好地理解有关dfs序的相关信息。

问题描述

一天,小蓝在他的小屋外发现了一颗神奇的树,它的树叶上闪烁着各种不同的颜色。小蓝对这颗树产生了浓厚的兴趣,于是他决定研究这颗树的奥秘。这棵树被称为"奇幻之树",因为它拥有神奇的能力。

每个节点都有自己独特的颜色,这些颜色代表了树上不同生物的种类。小蓝注意到,树的每个节点都有一个颜色标签 ci​ ,而这些颜色标签在树上不断变化,使得树上的生物多样性持续增加。

小蓝决定用算法来研究这颗树。他提出了一些问题,希望能够了解奇幻之树上不同颜色的种类数量。每次他会选择一颗树上的节点,然后探索以这个节点为根的子树中的颜色种类。

具体问题如下:给定一棵节点为 n 的有根树,根节点为 1 ,每个节点有一个颜色 ci,小蓝有 q 组询问,每次询问给定一个节点 x ,问 x 为根的子树中,有多少种不同的颜色。

小蓝很期待你能够帮助他解决这些有趣的问题,揭示奇幻之树的神奇之处。每次你回答一个询问,都会让小蓝对这颗树的理解更进一步,同时也会使他的奇幻之旅变得更加精彩。

输入格式

第一行输入两个整数 n,q。代表树的节点数量与询问数量。

接下来一行,输入 n 个整数 c1​,c2​,c3​...cn​ , 代表每个节点的颜色。

接下来 n−1 行,每行两个整数 ui​,vi​ ,代表存在一条边连接 ui​,vi​ 两点。

接下来 q 行, 每行一个整数 xi​ ,代表询问的点。

输出格式

输出 q 行,每行一个整数,代表每次询问的答案。

输入案例:

5 3
1 2 3 4 5
1 2
1 3
2 4
2 5
1
2
3

输出案例:

5
3
1
#include <bits/stdc++.h>
using namespace std;
using ll = long long;const int N = 1e5+5;
int n,c[N];
vector<int> g[N];
int sz[N],dfn[N],idx[N],tot;
int pre[N][101];void dfs(int x,int fa){sz[x]=1;dfn[x]=++tot;idx[dfn[x]]=x;for(const auto &y:g[x]){if(y==fa) continue;dfs(y,x);sz[x]+=sz[y];}
}void solve() {int x;cin>>x;int l=dfn[x],r=l+sz[x]-1;int ans=0;for(int i=1;i<=100;i++){if(pre[r][i]-pre[l-1][i]>0) ans++;}cout<<ans<<endl;
}
int main() {ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n;int q;cin>>q;for(int i=1;i<=n;i++) cin>>c[i];for(int i=2;i<=n;i++){int x,y;cin>>x>>y;g[x].push_back(y);g[y].push_back(x);}dfs(1,0);for(int i=1;i<=100;i++){for(int j=1;j<=n;j++){pre[j][i]=pre[j-1][i]+(c[idx[j]]==i);}}while(q--) {solve();}return 0;
}

这道题是经典的有关dfs序的问题,通过dfs序转化来对树中的有关问题进行求解分析,希望大家可以好好理解这道题目。

问题描述

给一棵含有 n 个结点的有根树,根结点为 1,编号为 i的点有点权 ai(i∈[1,n])。现在有两种操作,格式如下:

  • 1 x y:该操作表示将点 x 的点权改为 y。
  • 2 x:该操作表示查询以结点 x 为根的子树内的所有点的点权的异或和。

现有长度为 m的操作序列,请对于每个第二类操作给出正确的结果。

输入格式

输入的第一行包含两个正整数 n,m,用一个空格分隔。

第二行包含 n 个整数 a1​,a2​,…,an​,相邻整数之间使用一个空格分隔。

接下来 n−1行,每行包含两个正整数 ui​,vi​,表示结点 ui​ 和 vi​ 之间有一条边。接下来 m 行,每行包含一个操作。

输出格式

输出若干行,每行对应一个查询操作的答案。

输入案例:

4 4
1 2 3 4
1 2
1 3
2 4
2 1
1 1 0
2 1
2 2

输出案例:

4
5
6

代码部分:

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int wei[N],wi[N];
vector<int>a[N];
int cnt=0;
int in[N],out[N];
void dfs(int x,int fa){in[x]=++cnt;wi[in[x]]=wei[x];for(const auto&t:a[x]){if(t==fa)continue;dfs(t,x);}out[x]=cnt;
}
int main()
{int n,m;cin>>n>>m;for(int i=1;i<=n;i++)cin>>wei[i];for(int i=1;i<n;i++){int u,v;cin>>u>>v;a[u].push_back(v),a[v].push_back(u);}dfs(1,0);while(m--){int c;cin>>c;if(c==1){int x,y;cin>>x>>y;wi[in[x]]=y;}else{int d;cin>>d;int ans=0;for(int i=in[d];i<=out[d];i++){ans=ans^wi[i];}cout<<ans<<'\n';}}return 0;
}

这两道题都是通过dfs序来进行解决的,好了今天的分享就到这里,大家多多关注,后续也将继续进行相关内容分享。

http://www.lryc.cn/news/619858.html

相关文章:

  • WPF的c1FlexGrid的动态列隐藏和动态列名设置
  • 《设计模式之禅》笔记摘录 - 15.观察者模式
  • WMware的安装以及Ubuntu22的安装
  • MCP协议更新:从HTTP+SSE到Streamable HTTP,大模型通信的进化之路
  • 学习STM32 脉冲计数实验
  • 猫头虎AI分享:Word MCP,让AI具备Word文档操作能力,文档创建、内容添加、格式编辑等AI能力
  • HGDB的分区表实现SQL Server的分区视图
  • 健永科技工业自动化RFID解决方案
  • Maven配置Docker插件推送至远程私有仓库
  • 相机按键功能解析
  • python基于Hadoop的超市数据分析系统
  • SODA自然美颜相机(甜盐相机国际版) v9.3.0
  • 云手机未来的发展趋势如何?
  • 什么是智能对讲机?技术演进与参数指标解析
  • 服务器安全检测与防御技术总结
  • USB基础 -- USB相关协议字段解析
  • 高防IP的防护原理是什么?
  • Linux系统之ELF文件
  • BAV99WT1G ON安森美 双串联高速开关二极管 集成电路IC
  • Kafka工作机制深度解析:Broker、Partition 与消费者组协作原理
  • C# WPF本地Deepseek部署
  • WPF 开发的瑞士军刀:Prism 框架从入门到精通指南
  • webrtc弱网-QualityRampUpExperimentHelper类源码分析与算法原理
  • VMD+皮尔逊+降噪+重构(送报告+PPT)Matlab程序
  • 在前端js中使用jsPDF或react-to-pdf生成pdf文件时,不使用默认下载,而是存储到服务器
  • 存量竞争下的破局之道:品牌与IP的双引擎策略|创客匠人
  • 基于elk实现分布式日志
  • ELK开启安全策略
  • web安全开发,在线%射击比赛管理%系统开发demo,基于html,css,jquery,python,django,三层mysql数据库
  • 【微实验】基频提取的MATLAB实现(优化版)