Tree Compass( Codeforces Round 934 (Div. 2) )

Tree Compass( Codeforces Round 934 (Div. 2) )

You are given a tree with n n n vertices numbered 1 , 2 , … , n 1, 2, \ldots, n 1,2,,n. Initially, all vertices are colored white.

You can perform the following two-step operation:

  1. Choose a vertex v v v ( 1 ≤ v ≤ n 1 \leq v \leq n 1vn) and a distance d d d ( 0 ≤ d ≤ n − 1 0 \leq d \leq n-1 0dn1).
  2. For all vertices u u u ( 1 ≤ u ≤ n 1 \leq u \leq n 1un) such that dist † ( u , v ) = d \text{dist}^\dagger(u,v)=d dist(u,v)=d, color u u u black.

Construct a sequence of operations to color all the nodes in the tree black using the minimum possible number of operations. It can be proven that it is always possible to do so using at most n n n operations.

† ^\dagger dist ( x , y ) \text{dist}(x, y) dist(x,y) denotes the number of edges on the (unique) simple path between vertices x x x and y y y on the tree.

Input

Each test contains multiple test cases. The first line contains a single integer t t t ( 1 ≤ t ≤ 200 1 \leq t \leq 200 1t200) — the number of test cases. The description of the test cases follows.

The first line of each test case contains a single integer n n n ( 1 ≤ n ≤ 2 ⋅ 1 0 3 1 \le n \le 2 \cdot 10^3 1n2103) — the number of vertices of the tree.

The following n − 1 n - 1 n1 lines of each test case describe the edges of the tree. The i i i-th of these lines contains two integers u i u_i ui and v i v_i vi ( 1 ≤ u i , v i ≤ n 1 \le u_i, v_i \le n 1ui,vin, u i ≠ v i u_i \neq v_i ui=vi), the indices of the vertices connected by the i i i-th edge.

It is guaranteed that the given edges form a tree.

It is guaranteed that the sum of n n n over all test cases does not exceed 2 ⋅ 1 0 3 2 \cdot 10^3 2103.

Output

For each test case, first output a single integer o p op op ( 1 ≤ o p ≤ n ) (1 \le op \le n) (1opn), the minimum number of operations needed to color all vertices of the tree black.

Then, output o p op op lines, each containing 2 2 2 integers. The i i i-th line should contain the values of v v v and d d d chosen for the i i i-th operation ( 1 ≤ v ≤ n 1 \le v \le n 1vn, 0 ≤ d ≤ n − 1 0 \le d \le n - 1 0dn1)

You must guarantee that at the end of o p op op operations, all vertices are colored black.

If there are multiple solutions, you may output any one of them.

Example

Input

4121 241 21 31 472 73 26 45 71 66 7

Output

1
1 0
2
1 1
2 1
2
1 1
2 1
3
6 1
7 1
2 1

Note

In the first test case, there is only one possible operation, and performing it gives us a valid answer.

In the second test case, the first operation colors vertex 2 2 2 black, and the second operation colors vertex 1 1 1 black. It can be shown that it is impossible to color both vertices black in one operation, so the minimum number of operations needed is 2 2 2. Another possible solution is to use the 2 2 2 operations: ( u , r ) = ( 1 , 0 ) (u, r) = (1, 0) (u,r)=(1,0) and ( u , r ) = ( 2 , 0 ) (u, r) = (2, 0) (u,r)=(2,0).

In the third test case, the first operation colors vertices 2 2 2, 3 3 3 and 4 4 4 black, and the second operation colors vertex 1 1 1 black. Again, it can be shown that it is impossible to color all vertices black in 1 1 1 operation, so the minimum number of operations needed is 2 2 2.

In the fourth test case, the first operation colors vertices 4 4 4, 1 1 1 and 7 7 7 black, the second operation colors vertices 2 2 2, 5 5 5 and 6 6 6 black while the third operation colors vertices 3 3 3 and 7 7 7 black. Notice that it is allowed to color vertex 7 7 7 black twice.

Thus, each node was marked at least once, with node 7 7 7 marked twice. It can be shown that it is impossible to color all vertices black in fewer than 3 3 3 moves.

题解进一步分析和拓展

这个问题的关键在于树的直径,即树中两个最远节点之间的路径长度。直径的长度和树的染色策略有很大关系。接下来我们详细分析如何利用直径的性质优化我们的染色操作,并提出最优的染色方案。

一、直径链的染色操作

考虑一条长度为 (d) 的链,链上的每个节点都需要染色,操作一次最多能染黑链上的 2 个点。我们从树的直径出发,考虑如何使用最少的操作将所有节点染黑。

1. 直径 (d) 为奇数
  • 当直径 (d) 是奇数时,我们可以选择直径的中点 (u),然后进行一系列操作,操作的顺序是从 (u) 出发,染色 (u) 和与其距离为 (0, 1, 2, …, d-1) 的节点。这些操作的形式可以是:

    [
    (u, 0), (u, 1), (u, 2), …, (u, d-1)
    ]

    这样,通过最多 ( \frac{d+1}{2} ) 次操作,所有节点都能被染黑,因为每次操作都会把 2 个点染黑。

2. 直径 (d) 为偶数
  • 当直径 (d) 为偶数时,我们面临的挑战是如何通过最少次数的操作,覆盖整棵树的所有节点。这里分为两种情况:

    • 当 (d \mod 4 = 0)(即直径长度为 4 的倍数):
      我们可以选择直径的中心边 ( (x, y) ),然后交替地进行以下操作:

      [
      (x, 1), (y, 1), (x, 3), (y, 3), …, (x, d/2 - 1), (y, d/2 - 1)
      ]

      这样只需要 ( \frac{d}{2} ) 次操作。

    • 当 (d \mod 4 = 2)(即直径长度为 2 或 6 的余数为 2):
      由于不能完全通过交替操作来染色,我们只能从中心出发,进行如下操作:

      [
      (x, 0), (x, 1), (x, 2), …, (x, d/2)
      ]

      这样需要 ( \frac{d}{2} + 1 ) 次操作。

二、整体思路
  1. 找直径

    • 通过两次 DFS 来找到树的直径。第一次 DFS 从任意节点出发,找到最远的节点 (A);第二次 DFS 从 (A) 开始,找到最远的节点 (B),则 (A) 到 (B) 的路径即为树的直径。
  2. 根据直径的长度选择操作策略

    • 如果直径 (d) 为奇数,从中点出发进行操作。
    • 如果直径 (d) 为偶数,分为两种情况:
      • 如果 (d \mod 4 = 0),通过中心边交替操作。
      • 如果 (d \mod 4 = 2),从中心出发逐渐染色。
  3. 输出操作结果

    • 输出最少的操作次数和每次操作的具体节点及距离。

三、时间复杂度分析

  • DFS 查找直径的时间复杂度是 (O(n)),每次 DFS 都需要遍历整个树的节点和边,最多遍历 (n-1) 条边。
  • 操作计算 的时间复杂度是 (O(1)),因为操作次数由直径的长度确定,而直径已经通过 DFS 计算出来。
  • 因此,每个测试用例的时间复杂度是 (O(n)),而给定 (T) 个测试用例,所有测试用例的总时间复杂度为 (O(T \cdot n))。题目保证了总节点数 (n) 不超过 2000,所以这是一个高效的解法。

四、代码实现

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define BoBoowen ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int N = 2e3 + 10;int n;
vector<int> g[N];
int fa[N];
int started;
int ended;
int height;
vector<int> rode;void dfs1(int x, int f, int h)
{for (auto it : g[x]){if (it == f){continue;}dfs1(it, x, h + 1);}if (h > height){height = h;started = x;}
}void dfs2(int x, int f, int h)
{fa[x] = f;for (auto it : g[x]){if (it == f){continue;}dfs2(it, x, h + 1);}if (h > height){height = h;ended = x;}
}void cleared()
{for (int i = 0; i <= n; ++i){g[i].clear();fa[i] = 0;}height = 0;rode.clear();
}void solved()
{cin >> n;for (int i = 0; i < n - 1; ++i){int x, y;cin >> x >> y;g[x].push_back(y);g[y].push_back(x);}dfs1(1, 0, 1);// cout << started << endl;height = 0;dfs2(started, 0, 1);int now = ended;while (now != 0){rode.push_back(now);now = fa[now];}// cout << ended << endl;// for (auto it : rode)// {//     cout << it << ' ';// }// cout << endl;if (height % 2 == 1){cout << height / 2 + 1 << endl;for (int i = 0; i <= height / 2; ++i){cout << rode[height / 2] << ' ' << i << endl;}}else if (height % 4 == 0){cout << height / 2 << endl;for (int i = 1; i <= height / 2 - 1; i += 2){cout << rode[height / 2 - 1] << ' ' << i << endl;cout << rode[height / 2] << ' ' << i << endl;}}else{cout << height / 2 + 1 << endl;for (int i = 0; i <= height / 2; i++){cout << rode[height / 2 - 1] << ' ' << i << endl;}}cleared();
}signed main()
{BoBoowen;int T = 1;cin >> T;while (T--){solved();}
}

五、总结

  • 树的直径是这道题的核心,利用树的直径来优化染色操作,可以大幅减少操作次数。
  • 根据直径的长度,决定从中点出发进行染色或者采用交替操作,这样能够保证染色的最优性。
  • 时间复杂度为 (O(n)),对于每个测试用例能够在合理时间内求解出最少的染色操作次数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/69010.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【汽车电子软件架构】AutoSAR从放弃到入门专栏导读

本文是汽车电子软件架构&#xff1a;AutoSAR从放弃到入门专栏的导读篇。文章延续专栏文章的一贯作风&#xff0c;从概念与定义入手&#xff0c;希望读者能对AutoSAR架构有一个整体的认识&#xff0c;然后对专栏涉及的文章进行分类与链接。本文首先从AutoSAR汽车软件架构的概念&…

python-UnitTest框架笔记

UnitTest框架的基本使用方法 UnitTest框架介绍 框架&#xff1a;framework&#xff0c;为了解决一类事情的功能集合 UnitTest框架&#xff1a;是python自带的单元测试框架 自带的&#xff0c;可以直接使用&#xff0c;不需要格外安装 测试人员用来做自动化测试&#xff0c;作…

【数据结构】_链表经典算法OJ:复杂链表的复制

目录 1. 题目链接及描述 2. 解题思路 3. 程序 1. 题目链接及描述 题目链接&#xff1a;138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;…

Linux——进程间通信之SystemV共享内存

前言 SystemV通信一般包括三种&#xff1a;共享内存、消息队列和信号量。共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到 内核&#xff0c;换句话说是进程不再通过执行进入内核的系统调用来…

Linux网络 | 网络层IP报文解析、认识网段划分与IP地址

前言&#xff1a;本节内容为网络层。 主要讲解IP协议报文字段以及分离有效载荷。 另外&#xff0c; 本节也会带领友友认识一下IP地址的划分。 那么现在废话不多说&#xff0c; 开始我们的学习吧&#xff01;&#xff01; ps&#xff1a;本节正式进入网络层喽&#xff0c; 友友们…

SQLGlot:用SQLGlot解析SQL

几十年来&#xff0c;结构化查询语言&#xff08;SQL&#xff09;一直是与数据库交互的实际语言。在一段时间内&#xff0c;不同的数据库在支持通用SQL语法的同时演变出了不同的SQL风格&#xff0c;也就是方言。这可能是SQL被广泛采用和流行的原因之一。 SQL解析是解构SQL查询…

Windows程序设计10:文件指针及目录的创建与删除

文章目录 前言一、文件指针是什么&#xff1f;二、设置文件指针的位置&#xff1a;随机读写&#xff0c;SetFilePointer函数1.函数说明2.函数实例 三、 目录的创建CreateDirectory四、目录的删除RemoveDirectory总结 前言 Windows程序设计10&#xff1a;文件指针及目录的创建与…

线程互斥同步

前言&#xff1a; 简单回顾一下上文所学&#xff0c;上文我们最重要核心的工作就是介绍了我们线程自己的LWP和tid究竟是个什么&#xff0c;总结一句话&#xff0c;就是tid是用户视角下所认为的概念&#xff0c;因为在Linux系统中&#xff0c;从来没有线程这一说法&#xff0c;…

DRM系列七:Drm之CREATE_DUMB

本系列文章基于linux 5.15 DRM驱动的显存由GEM&#xff08;Graphics execution management&#xff09;管理。 一、创建流程 创建buf时&#xff0c;user层提供需要buf的width,height以及bpp(bite per pixel)&#xff0c;然后调用drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &…

我们信仰AI?从神明到人工智能——信任的进化

信任的进化&#xff1a; 信任是我们最宝贵的资产。而现在&#xff0c;它正像黑色星期五促销的廉价平板电视一样&#xff0c;被一点点拆解。在过去&#xff0c;世界很简单&#xff1a;人们相信晚间新闻、那些满是灰尘书籍的教授&#xff0c;或者手持病历、眉头紧锁的医生。而如…

数据分析系列--[11] RapidMiner,K-Means聚类分析(含数据集)

一、数据集 二、导入数据 三、K-Means聚类 数据说明:提供一组数据,含体重、胆固醇、性别。 分析目标:找到这组数据中需要治疗的群体供后续使用。 一、数据集 点击下载数据集 二、导入数据 三、K-Means聚类 Ending, congratulations, youre done.

1-刷力扣问题记录

25.1.19 1.size()和.length()有什么区别 2.result.push_back({nums[i], nums[left], nums[right]});为什么用大括号&#xff1f; 使用大括号 {} 是 C11 引入的 初始化列表 语法&#xff0c;它允许我们在构造或初始化对象时直接传入一组值。大括号的使用在许多情况下都能让代码…

神经网络参数量和运算量的计算- 基于deepspeed库和thop库函数

引言 最近需要对神经网络的参数量和运算量进行统计。找到一个基于deepspeed库函数计算参数量和运算量的例子。而我之前一直用thop库函数来计算。 看到有一篇勘误博文写道使用thops库得到的运算量是MACs (Multiply ACcumulate operations&#xff0c;乘加累积操作次数&#xf…

读书笔记--分布式架构的异步化和缓存技术原理及应用场景

本篇是在上一篇的基础上&#xff0c;主要对分布式应用架构下的异步化机制和缓存技术进行学习&#xff0c;主要记录和思考如下&#xff0c;供大家学习参考。大家知道原来传统的单一WAR应用中&#xff0c;由于所有数据都在同一个数据库中&#xff0c;因此事务问题一般借助数据库事…

无用知识研究:std::initializer_list的秘密

先说结论&#xff0c;用std::initializer_list初始化vector&#xff0c;内部逻辑是先生成了一个临时数组&#xff0c;进行了拷贝构造&#xff0c;然后用这个数组的起终指针初始化initializer_list。然后再用initializer_list对vector进行初始化&#xff0c;这个动作又触发了拷贝…

Jupyterlab和notebook修改文件的默认存放路径的方法

文章目录 1.缘由2.操作流程2.1找到默认的路径2.2创建配置文件2.3修改配置文件内容2.4注意事项 1.缘由 我自己使用jupyterlab的时候&#xff0c;打开是在这个浏览器上面打开的&#xff0c;但是这个打开的文件路径显示的是C盘上面路径&#xff0c;所以这个就很麻烦&#xff0c;因…

HarmonyOS:ArkWeb进程

ArkWeb是多进程模型,分为应用进程、Web渲染进程、Web GPU进程、Web孵化进程和Foundation进程。 说明 Web内核没有明确的内存大小申请约束,理论上可以无限大,直到被资源管理释放。 ArkWeb进程模型图 应用进程中Web相关线程(应用唯一) 应用进程为主进程。包含网络线程、Vi…

基于Spring Security 6的OAuth2 系列之九 - 授权服务器--token的获取

之所以想写这一系列&#xff0c;是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器&#xff0c;但当时基于spring-boot 2.3.x&#xff0c;其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0&#xff0c;结果一看Spring Security也升级…

音标-- 02-- 重音 音节 变音

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 国际音标1.重音2.音节3.变音 国际音标 1.重音 2.音节 3.变音

Adaptive LLM Transformer²

看到了一个不错的论文https://arxiv.org/pdf/2501.06252 TRANSFORMER-SQUARED: SELF-ADAPTIVE LLMS 挺有意思的&#xff0c;是一家日本AI公司SakanaAI的论文&#xff08;我以前写过他们的不训练提升模型的能力的文章&#xff0c;感兴趣可以去翻&#xff09;它家有Lion Jones坐镇…