【CF】1695D1-Tree Queries(Easy Version) 题解

2024-08-28 03:28

本文主要是介绍【CF】1695D1-Tree Queries(Easy Version) 题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门:1695D1
标签:动态规划

题目大意

给定一棵无根树,其中包含n个顶点。在树中隐藏了一个未知的顶点x,你需要通过查询来找出这个顶点。你可以进行k次查询,每次查询选择一个顶点v_i,在完成所有查询后,你会得到k个数字d_1, d_2, …, d_k,其中d_i表示从v_i到顶点x的最短路径上的边的数量。请注意,你知道每个距离对应哪个查询。请确定最小的k值,使得存在一些查询v_1, v_2, …, v_k,这些查询总能让你唯一地识别出顶点x,你不需要实际输出这些查询。

输入:文件的第一行包含一个整数t(1≤t≤100),表示测试用例的数量。接下来是对测试用例的描述。每个测试用例的第一行包含一个整数n(1≤n≤2000),表示树中的顶点数量。接下来的n-1行每行包含两个整数x和y(1≤x,y≤n),表示在树中有一条连接顶点x和y的边。
保证给出的边形成了一个树。保证所有测试用例的n之和不超过2000。

输出格式:对于每个测试用例,输出一个非负整数,表示所需的最少查询次数。

算法分析

  • 如果n=1,则无需任何查询,因为只有一个顶点。否则,我们需要至少一次查询。如果我们固定一个节点u,并强制它成为查询,我们可以将树根固定在u上,并执行贪婪DFS以计算答案。需要注意的是,因为我们保证了根是一个查询,所以当我们为任何节点v计算答案时,我们可以假设要么是v要么是不在v子树中的某个顶点已经被查询过了。
  • 我们定义ans[v]为区分v子树内所有顶点所需的最小查询次数,前提是v或不在v子树内的某个顶点已经进行了查询。注意到对于v的所有孩子c,我们需要能够区分c子树内的所有顶点,因此我们有ans[v]≥∑c ans[c]。此外,最多只能有一个孩子c的子树没有查询,否则这些孩子的所有子树都将无法通过查询区分开。如果有x>1这样的孩子,我们可以查询前x-1个孩子,这样就足以区分这些x个子树中的所有顶点。使用这个x的定义,我们的最终公式是:ans[v]=∑c ans[c]+max(0,x−1)
  • 对于每个可能的根,我们递归地执行DFS来计算这些答案。答案是最小的ans[root]+1,其中+1是因为我们要对根进行查询。复杂度:O(n^2)

代码实现

#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
int t, n;
int d[N];
vector<int> e[N];int dfs(int u, int fa){int cnt = 0, sum = 0;for (auto v : e[u]){if (v == fa) continue;int x = dfs(v, u);sum += x;if (!x) cnt ++ ;}return sum + max(0, cnt - 1);
}void solve(){cin >> n;for (int i = 1; i <= n; i ++ ){e[i].clear();d[i] = 0;}for (int i = 1; i < n; i ++ ){int u, v;cin >> u >> v;e[u].push_back(v);e[v].push_back(u);d[u] ++ , d[v] ++ ;}if (n == 1){cout << 0 << '\n';return;}int ans = 0;for (int i = 1; i <= n; i ++ ){ans = max(ans, max(1, dfs(i, 0)));}cout << ans << '\n';
}int main(){cin >> t;while (t -- ) solve();return 0;
}

这篇关于【CF】1695D1-Tree Queries(Easy Version) 题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1113591

相关文章

提示:Decompiled.class file,bytecode version如何解决

《提示:Decompiled.classfile,bytecodeversion如何解决》在处理Decompiled.classfile和bytecodeversion问题时,通过修改Maven配... 目录问题原因总结问题1、提示:Decompiled .class file,China编程 bytecode

cf 164 C 费用流

给你n个任务,k个机器,n个任务的起始时间,持续时间,完成任务的获利 每个机器可以完成任何一项任务,但是同一时刻只能完成一项任务,一旦某台机器在完成某项任务时,直到任务结束,这台机器都不能去做其他任务 最后问你当获利最大时,应该安排那些机器工作,即输出方案 具体建图方法: 新建源汇S T‘ 对任务按照起始时间s按升序排序 拆点: u 向 u'连一条边 容量为 1 费用为 -c,

CF 508C

点击打开链接 import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String [] args){new Solve().run() ;} }class Solve{int bit[] = new int[608] ;int l

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

Maven创建项目中的groupId, artifactId, 和 version的意思

文章目录 groupIdartifactIdversionname groupId 定义:groupId 是 Maven 项目坐标的第一个部分,它通常表示项目的组织或公司的域名反转写法。例如,如果你为公司 example.com 开发软件,groupId 可能是 com.example。作用:groupId 被用来组织和分组相关的 Maven artifacts,这样可以避免

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

树(Tree)——《啊哈!算法》

树 什么是树?树是一种特殊的图,不包含回路的连通无向树。 正因为树有着“不包含回路”这个特点,所以树就被赋予了很多特性。 一棵树中的任意两个结点有且仅有唯一的一条路径连通。一棵树如果有n个结点,那么它一定恰好有n-1条边。在一棵树中加一条边将会构成一个回路。 一棵树有且只有一个根结点。 没有父结点的结点称为根结点(祖先)。没有子结点的结点称为叶结点。如果一个结点既不是根结点也不是叶

【秋招笔试】9.07米哈游秋招改编题-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收集 100+ 套笔试题,笔试真题 会在第一时间跟新 🍄 题面描述等均已改编,如果和你笔试题看到的题面描述

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析