E. Gardener and Tree 树形DP

本文介绍了如何通过两次深度优先搜索(DFS)来解决一个关于图中节点保留问题。首先计算每个节点的最长路径,然后在第二次搜索中考虑父节点对子节点次长路径的影响,以确定在k次操作后哪些节点会被保留。核心在于利用dp1和dp2数组存储路径长度信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

题目描述

在这里插入图片描述

思路

  1. 求一下每个结点的所有分支路径中第二长的那条路径的长度,如果长度大于K,那么k次操作后这个结点就会被保留。

  2. 做两次dfs第一次,沿着这个固定结点往下搜索,求得最长路径长度,并且记录当前结点的最长路径是来自哪个结点的(第二次搜索会用到)。

  3. 为什么做两次搜索
    第一次搜索后除了第一个结点,其它结点的最长路径都没有考虑到其经过父节点的那条路径,所以要再用第一次的根节点搜索一次,对每个结点,考虑父节点路径对它的第二长路径答案的影响,要特判父节点的最长路是不是就是自己的路径对其的贡献,如果是,就考虑父节点次长路径,对当前结点的次长路径的影响。


具体实现看代码

#include<bits/stdc++.h>
using namespace std;
const int N = 4E5 + 10;
int ma[N],h[N],to[N << 1],ne[N << 1],dp1[N],dp2[N];
// ma数组记录当前结点的最长路径来自哪个子结点
//dp1数组记录最长路径长度,dp2记录次长路径长度

int cnt = 0;
void add(int x,int y){
	to[++cnt] = y;
	ne[cnt] = h[x];
	h[x] = cnt;
}

int dfs(int u,int fa){
	dp1[u] = dp2[u] = 1;
	int d1,d2; d1 = d2 = 0;
	for(int i = h[u]; ~i; i = ne[i]){
		int v = to[i];
		if(v == fa)
			continue;
		int d = dfs(v,u) + 1;
		if(d > d1) d2 = d1,d1 = d,ma[u] = v;
		else if(d > d2)	d2 = d;
	}
	dp1[u] = max(d1,1);
	dp2[u] = max(d2,1);
	return dp1[u];
}

void dfs_f(int u,int fa){
	if(~fa){
		if(ma[fa] != u){
			if(dp1[fa] + 1 > dp1[u]){
				dp2[u] = dp1[u];
				dp1[u] = dp1[fa] + 1;
 			}
		}else if(dp2[fa] + 1 > dp1[u]){
			dp2[u] = dp1[u];
			dp1[u] = dp2[fa] + 1;
		}else dp2[u] = max(dp2[u],dp2[fa] + 1);
	}
	for(int i = h[u]; ~i; i = ne[i]){
		int v = to[i];
		if(v == fa)
			continue;
		dfs_f(v,u);
	}
}

int main(){
	int T;	cin >> T;
	while(T--){
		int n,k;	cin >> n >> k;
		memset(h,-1,sizeof h);
		cnt = 0;
		for(int i = 1; i < n; ++i){
			int x,y;	cin >> x >> y;
			add(x,y);	add(y,x);
		}
		dfs(1,-1);// 第一次搜索求最短路 和 最长路
		

		dfs_f(1,-1);//第二次搜索对每个结点考虑父节点对该结点答案的影响
		
		int ans = 0;
		for(int i = 1; i <= n; ++i){// 如果次长路径长度大于k那么这个结点最后就可以被保留
			if(dp2[i] > k) 	++ans;	 
		}
		
		cout << ans << '\n';
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值