首页 > 其他分享 >dfs序专题训练

dfs序专题训练

时间:2024-04-12 20:12:22浏览次数:26  
标签:专题 idx 训练 int value dep dfs id

DFS序专题

NC13611 https://ac.nowcoder.com/acm/problem/13611

题意:要求树上任意两点相同颜色之间的路径上的点也是相同颜色,k种颜色,求方案数

Solution:原问题等价于将树分割成若干连通块且相互之间颜色不同

其实是道数论题。 题意可以转化为将树分割为不超过 \(k\) 个连通块,每个连通块颜色不同。若将树分割为 \(i\) 个连通块,则需要删去 \(i-1\) 条边,故方案数为 \(\mathrm{C}_{n-1}^{i-1}\) 。同时,要从 \(k\) 种颜色中选出 \(i\) 中颜色染色,而且是有顺序的,故方案数为 \(\mathrm{A}_{k}^{i}\) 。 综上,总的方案数为: \(ans= \sum_{i=1}^{\min(n,k)}\mathrm{C}_{n-1}^{i-1}\mathrm{A}_{k}^{i}\) 可以线性求逆元,枚举 \(i\) 实现。 时间复杂度:\(O(n)\) 。

Code

void init(int n) {
    inv[0]=inv[1]=1;
    for (int i=2;i<=n;i++) inv[i] = (mod-mod/i)*inv[mod%i]%mod;
for (int i = 2; i <= n; i++) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
    finv[1] = f[1] = finv[0] = f[0] = 1;
    for (int i = 2; i <= n; i++) finv[i] = finv[i - 1] * inv[i] % mod;
    for (int i = 2; i <= n; i++) f[i] = f[i - 1] * i % mod;
 
}
int C(int a,int b){
	if(a==0||b==0)return 1;
	return f[a]*finv[a-b]%mod*finv[b]%mod;
}
int A(int a,int b){
	if(a==0||b==0)return 1;
	return f[a]*finv[a-b]%mod;
}
void solve(){
	
	int k;cin>>n>>k;
	init(n);
	for(int i=1;i<=n-1;i++){
		int u,v;cin>>u>>v;
	}
	int ans=0;
	for(int i=1;i<=min(n,k);i++){
		ans+=C(n-1,i-1)*A(k,i)%mod;
		ans%=mod;
	}
	cout<<ans<<endl;
}

本题如果不考虑组合数学,还可以从dp的角度考虑,我们先做一遍dfs序然后在序列上考虑。用f[i] [j] 表示树上dfs序的前i个点用了j种颜色的方法数$ f[i] [j] = f[i-1] [j] + f[i-1] [j-1] \times (k-j+1) $

  • 对于当前节点,如果选之前的颜色那么只能和父节点颜色相同,和其他点颜色相同也会必经父节点。
  • 如果不选之前的颜色,则有剩余没被选的颜色种选择

dfs序模板题

https://codeforces.com/problemset/problem/1006/E

题意:每次静态查询某个节点子树第k个被访问的点,访问顺序是以编号小的优先。

int l[N];
int r[N];
vector<int>e[N];
int idx=0;
int dfn[N];
int rk[N];
void dfs(int u,int fa){
	l[u]=++idx;
	dfn[u]=idx;
	rk[idx]=u;
	for(auto v:e[u]){
		if(v==fa)continue;
		dfs(v,u);
	}
	r[u]=idx;
}
void solve(){
   cin>>n>>m;
   for(int i=2;i<=n;i++){
   	int x;cin>>x;
   
   	 e[x].push_back(i);

   }
   dfs(1,0);
   for(int i=1;i<=m;i++){
   	int u,k;cin>>u>>k;
   	int len=r[u]-l[u]+1;
   	if(len<k)cout<<-1<<endl;
   	else {
   		int pos=l[u]+k-1;
   		cout<<rk[pos]<<endl;
   	}
   }
   
}

NC22494

链接:https://ac.nowcoder.com/acm/problem/22494
来源:牛客网

题面:有一棵n个节点的二叉树,1为根节点,每个节点有一个值wi。现在要选出尽量多的点。 对于任意一棵子树,都要满足: 如果选了根节点的话,在这棵子树内选的其他的点都要比根节点的值; 如果在左子树选了一个点,在右子树中选的其他点要比它

题意:选的点需要满足点权值根<右<左,我们考虑dfs序按照这个偏序关系进行从而得到一个序列,所以我们只需要找到LIS,由于数据范围是1e5,所以我们需要使用单调栈加二分的方式去找到最长严格上升子序列

int a[N];

int lc[N],rc[N];
int ans[N];int idx=0;
void dfs(int u){
	if(u==0)return ;
	ans[++idx]=u;
	dfs(rc[u]);
	dfs(lc[u]);
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++){
		cin>>lc[i]>>rc[i];
	}
dfs(1);
vector<int>v;
for(int i=1;i<=n;i++){
	int id=ans[i];
	v.push_back(a[id]);
}
vector<int>ls;
for(int i=0;i<(int)v.size();i++){
	//cerr<<v[i]<<endl;
	if(ls.empty()||v[i]>ls.back())ls.push_back(v[i]);
	else {
int pos=lower_bound(ls.begin(),ls.end(),v[i])-ls.begin();
	ls[pos]=v[i];
	}
}
int res=ls.size();
//res++;
cout<<res<<endl;

}

开始利用dfs序进行树上常规数据结构操作

链接:https://ac.nowcoder.com/acm/problem/204871

已知有 \(n\) 个节点,有 \(n-1\) 条边,形成一个树的结构。 给定一个根节点 \(k\),每个节点都有一个权值,节点i的权值为 \(v_i\)。 给 \(m\) 个操作,操作有两种类型:

  • 1 a x :表示将节点 \(a\) 的权值加上 \(x\)
  • 2 a :表示求 \(a\) 节点的子树上所有节点的和(包括 \(a\) 节点本身)

题意:进行在线的单点修改和子树点权和查询

Solution:利用dfs序转到序列问题,显然可以用树状数组维护

vector<int>e[N];
int l[N],r[N];
int idx=0;
void dfs(int u,int fa){
	l[u]=++idx;
	for(auto v:e[u]){
		if(v==fa)continue;
		dfs(v,u);
	}
	r[u]=idx;
}

void solve(){
	cin>>n;
	cin>>m;
	int root;cin>>root;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n-1;i++){
		int u,v;cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	Fenwick<int>c(n+1);
	dfs(root,0);
	for(int i=1;i<=n;i++){
		c.add(l[i],a[i]);
	}
	for(int i=1;i<=m;i++){
		int op;cin>>op;
		if(op==1){
			int id,val;
			cin>>id>>val;
			c.add(l[id],val);
		}
		else {
			int pos;cin>>pos;
			int ql=l[pos],qr=r[pos];
			int ans=c.rangeSum(ql-1,qr);
			cout<<ans<<endl;
		}
	}
}

考察离线思想的dfs序上树状数组

链接:https://ac.nowcoder.com/acm/problem/23051

华华和月月一起维护了一棵动态有根树,每个点有一个权值。刚开存档的时候,树上只有 0 号节点,权值为 0 。接下来有两种操作:

  • 操作 1:输入格式\(1\ i\),表示月月氪金使节点 i 长出了一个新的儿子节点,权值为0,编号为当前最大编号 +1(也可以理解为,当前是第几个操作 1,新节点的编号就是多少)。

  • 操作 2:输入格式 \(2 \ i \ a\),表示华华上线做任务使节点 i 的子树中所有节点(即它和它的所有子孙节点)权值加 a 。 但是月月有时会检查华华有没有认真维护这棵树,会作出询问:

  • 询问 3:输入格式\(3\ i\),华华需要给出 i 节点此时的权值。

Solution:

标签:专题,idx,训练,int,value,dep,dfs,id
From: https://www.cnblogs.com/mathiter/p/18132005

相关文章

  • day2-Python训练营
    1.ClassOne1.如何正确关闭一个Vmware中的虚拟机2.为Ubuntu安装一些软件step1:openterminal或者快捷键ctrl+shift+T打开终端,然后ping一下,看网络是否连通。step2:sudoaptupdate,判断安装源(默认是美国的源,类似于软件商店)是否连通;step3:安装两个软件,ssh和vim,sudoaptin......
  • 即时通讯技术文集(第36期):《跟着源码学IM》系列专题 [共12篇]
    为了更好地分类阅读52im.net总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第36 期。[-1-] 跟着源码学IM(一):手把手教你用Netty实现心跳机制、断线重连机制[链接] http://www.52im.net/thread-2663-1-1.html[摘要] 说到用Netty来开发IM或推送系统,以一个......
  • 蓝桥杯训练
    P8712[蓝桥杯2020省B1]整数拼接-洛谷|计算机科学教育新生态(luogu.com.cn)题解:这道题和牛客类似,我们换一个思路我们可以开一个二维数组  一位用来记录拼在后面数的长度,一个用来记录这个数乘上10的(后面数的长度)模10我们直接乘1到10,全部记录下来然后枚举右边的数,看......
  • 算法训练营Day08-LeetCode344. 反转字符串 && 541. 反转字符串 II && 151. 反转字符串
    344.反转字符串题目链接:LeetCode344.反转字符串编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题思路:字符串首尾字符交换即可完成反转。定......
  • 数据是一维数据,利用tensorflow深度学习框架,写一个带自注意力机制的卷积神经网络,并进行
    下面是一个使用TensorFlow框架的带有自注意力机制的卷积神经网络(Self-AttentionConvolutionalNeuralNetwork)的示例代码,包括数据处理、模型定义和训练过程:importtensorflowastffromtensorflow.keras.layersimportConv1D,Dense,GlobalMaxPooling1D,Concatenate#......
  • 2024SMU蓝桥训练2补题
    C-密文搜索思路:不难。voidsolve(){//C--密文搜索可以不是字符串哈希--因为只需要知道相同长度字符串对字母出现情况,可以对字符串进行!!!排序!!!stringstr;cin>>str;intn,ans=0;cin>>n;unordered_map<string,int>mp;for(inti=1;i<=n;i++){......
  • P9669 [ICPC2022 Jinan R] DFS Order 2
    P9669[ICPC2022JinanR]DFSOrder2树形dp+回退背包dfs的过程时走到\(u\),如果走进一个子树后要回到\(u\),那么这个子树一定全部遍历了一遍。所以方案数会跟子树遍历的方案数有关,可以预处理。设\(h_u\)表示\(u\)子树的遍历方案,假如\(u\)有\(m\)个儿子,那么有\(h_u=......
  • 【专题】2024年中国游戏营销趋势报告合集PDF分享(附原数据表)
    原文链接:https://tecdat.cn/?p=35745原文出处:拓端数据部落公众号2023年,全球游戏行业表现卓越,不仅用户规模扩大至33.81亿,行业营收也攀升至1.35万亿人民币,呈现出强劲的增长态势。然而,与此同时,全球游戏创业公司在风险投资上的大幅缩减也揭示了行业面临的某些挑战。阅读原文,获取专题......
  • 买瓜-dfs
    6.买瓜-蓝桥云课(lanqiao.cn)#include<bits/stdc++.h>#defineintlonglong#defineendl'\n'usingnamespacestd;intn,m,a[35],cnt=40,sum[35];//x是当前编号,w是当前总重量,c是当前劈了多少个瓜voiddfs(intx,intw,intc){ if(w==m){//如果当前重量符合要......
  • MXnet安装 与入门 符号式运算 Symbol 数据同步 KVStore 自动并行计算 数据的导出与载
    MXnet参考通过MXNet/Gluon来动手学习深度学习在线githubpdf代码深度学习库MXNet由dmlc/cxxnet,dmlc/minerva和Purine2的作者发起,融合了Minerva的动态执行,cxxnet的静态优化和Purine2的符号计算等思想,直接支持基于Python的parameterserver接口,使......