题目传送门

细节较多的构造题。

解决思路

题目中虽然说是无根树,但我们可以钦定这棵树的根为 1,方便构造,这是不影响结果的。

以下记给定的三段长度为 \(a,b,c\) 。

先考虑无解的情况。

  • 首先,给出的三个距离,任意两者之和必须大于等于第三者,否则显然无解。

  • 其次,用到的边数不能\(\ge n\)。

  • 最后,两个节点的 \(\text{LCA}\) 到根节点的距离 (绿色) 是整数,两节点之间最短距离 (蓝色) 也是整数,而 \(a+b+c\) 正好是蓝色绿色各算两次,所以 \(a+b+c\) 必须是偶数。

然后考虑如何构造。

为了方便,我们钦定 2 离根节点距离较小的一个。可以事先比较并做交换,输出时修改一下。

一种比较简单的想法:

给一组例子:

  1. 10 5 5 4

首先把 23 可以公共的部分输出。公共祖先数 (不包括 1) 可以这样

算: \((a+c-b)/2\)(想一想为什么)。输出的 \(now\) (当前填充节点)应该从 4 开始,\(lst\)(上一个节点)初始设为 1,之后每一次将 \(lst\) 更新为 \(now\),然后将 \(now +1\) 。

处理完会变成这样:

然后从当前扩展到的节点分别向两侧延伸,记已经输出的公共祖先数为 \(cnt\),那么 2 还需拓展的点数为 \(a-cnt-1\),3 还需拓展的点数为 \(b-(a-cnt)-1\) 。像之前一样分别向两边拓展即可。注意拓展 2 之前先把 \(lst\) 暂存下来,方便之后拓展 3 时将 \(lst\) 归位。

处理完会变成这样:

最后还剩的点全部连到 1 上即可(连其他地方也没事)。

所以这个样例最后一组可行的解就是这样:

先给出这一部分的代码:

  1. int _1=2,_2=3;
  2. if(a>c){
  3. swap(a,c);
  4. swap(_1,_2);
  5. }
  6. int lst=1,now=4,cnt=0;
  7. for(int i=1;i<=(a+c-b)/2;i++){
  8. cout<<lst<<' '<<now<<endl;
  9. lst=now,now++,cnt++;
  10. }
  11. a-=cnt,c-=cnt;
  12. int t1=lst;
  13. for(int i=1;i<a;i++){
  14. cout<<lst<<' '<<now<<endl;
  15. lst=now,now++;
  16. }
  17. cout<<lst<<' '<<_1<<endl;
  18. lst=t1;
  19. for(int i=1;i<b-a;i++){
  20. cout<<lst<<' '<<now<<endl;
  21. lst=now,now++;
  22. }
  23. cout<<lst<<' '<<_2<<endl;
  24. for(int i=now;i<=n;i++) cout<<1<<' '<<i<<endl;

然而这样写却 \(\text{WA}\) 了。对照错误样例 通过仔细思考,我们可以发现一种特殊情况,比如:

  1. 6 2 3 5

这时,以上的程序给出了一个离谱的错误答案。手玩发现,这种特殊情况是整棵树恰好为一条链:

这时,较近的点为较远的点的祖先,也就是 \(a+b=c\) 。

所以,只需要特判出来,按照链的特点,用类似方法构造即可。

AC Code

  1. #include<bits/stdc++.h>
  2. #define IOS ios::sync_with_stdio(false)
  3. #define TIE cin.tie(0),cout.tie(0)
  4. using namespace std;
  5. int T,n,a,b,c,d1,d2,d3;
  6. void solve(){
  7. cin>>n>>a>>b>>c;
  8. d1=(a+c-b)/2;
  9. d2=(a+b-c)/2;
  10. d3=(b+c-a)/2;
  11. if(d1<0||d2<0||d3<0||d1+d2+d3>=n||(a+b+c)%2){
  12. cout<<"NO"<<endl;
  13. return ;
  14. }
  15. cout<<"YES"<<endl;
  16. int _1=2,_2=3;
  17. if(a>c){
  18. swap(a,c);
  19. swap(_1,_2);
  20. }
  21. int lst=1,now=4,cnt=0;
  22. if(a+b==c){
  23. for(int i=1;i<a;i++){
  24. cout<<lst<<' '<<now<<endl;
  25. lst=now,now++;
  26. }
  27. cout<<lst<<' '<<_1<<endl;
  28. lst=_1;
  29. for(int i=1;i<b;i++){
  30. cout<<lst<<' '<<now<<endl;
  31. lst=now,now++;
  32. }
  33. cout<<lst<<' '<<_2<<endl;
  34. }
  35. else{
  36. for(int i=1;i<=(a+c-b)/2;i++){
  37. cout<<lst<<' '<<now<<endl;
  38. lst=now,now++,cnt++;
  39. }
  40. a-=cnt,c-=cnt;
  41. int t1=lst;
  42. for(int i=1;i<a;i++){
  43. cout<<lst<<' '<<now<<endl;
  44. lst=now,now++;
  45. }
  46. cout<<lst<<' '<<_1<<endl;
  47. lst=t1;
  48. for(int i=1;i<b-a;i++){
  49. cout<<lst<<' '<<now<<endl;
  50. lst=now,now++;
  51. }
  52. cout<<lst<<' '<<_2<<endl;
  53. }
  54. for(int i=now;i<=n;i++) cout<<1<<' '<<i<<endl;
  55. }
  56. int main(){
  57. IOS;TIE;
  58. cin>>T;
  59. while(T--) solve();
  60. return 0;
  61. }

【笔记】CF1714F Build a Tree and That Is It 及相关的更多相关文章

  1. 【题解】CF1714F Build a Tree and That Is It

    题面传送门 解决思路 题目中虽然说是无根树,但我们可以钦定这棵树的根为节点 \(1\),方便构造,这是不 影响结果的. 以下记给定的三段长度为 \(a,b,c\). 先考虑无解的情况. 首先,给出的三 ...

  2. HDU 6121 Build a tree(找规律+模拟)

    Build a tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)To ...

  3. hdu6121 Build a tree 模拟

    /** 题目:hdu6121 Build a tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6121 题意:n个点标号为0~n-1:节点i的父节点 ...

  4. hdu6121 Build a tree

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6121 题面: Build a tree Time Limit: 2000/1000 MS (J ...

  5. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  6. 2017ACM暑期多校联合训练 - Team 7 1002 HDU 6121 Build a tree (深搜+思维)

    题目链接 Problem Description HazelFan wants to build a rooted tree. The tree has n nodes labeled 0 to n− ...

  7. HDU 6121 Build a tree —— 2017 Multi-University Training 7

    HazelFan wants to build a rooted tree. The tree has nn nodes labeled 0 to n−1, and the father of the ...

  8. Vue.js学习笔记(6)tree

    分享一段用 <ul>和<li>标签实现tree的代码,可能写的不是很好,如果大家有更好的希望和小颖分享下.嘻嘻 啦啦啦,代码看这里喽: <div class=" ...

  9. 机器学习技法笔记:09 Decision Tree

    Roadmap Decision Tree Hypothesis Decision Tree Algorithm Decision Tree Heuristics in C&RT Decisi ...

随机推荐

  1. 【Java】学习路径44-多线程入门篇

    这一章,我们学习线程的创建.线程的启动.线程的名字设置.线程的休眠.线程的加入.守护线程. 一个线程是一个单独的类的对象. 想让一个普通的类变成多线程,那么这个类需要继承Thread. 创建多线程的步 ...

  2. 通过宏封装实现std::format编译期检查参数数量是否一致

    背景 std::format在传参数量少于格式串所需参数数量时,会抛出异常.而在大部分的应用场景下,参数数量不一致提供编译报错更加合适,可以促进我们更早发现问题并进行改正. 最终效果 // 测试输出接 ...

  3. 搭建docker镜像仓库(二):使用harbor搭建本地镜像仓库

    目录 一.系统环境 二.前言 三.Harbor 四.使用harbor搭建私有镜像仓库 4.1 环境介绍 4.2 k8smaster节点安装配置harbor 4.2.1 安装harbor离线包 4.2. ...

  4. git hooks在业务中的使用

    起因 最近公司项目发生了一起线上事故,最后排查下来是配置文件的问题.项目里application.yml文件内会用@build.time@记录打包时的时间,但是这个写法是build-helper-ma ...

  5. 动态调整日志级别思路&实现

    引言 上篇文章 性能调优--小小的 log 大大的坑 已将详细的介绍了高并发下,不正确的使用日志姿势,可能会导致服务性能急剧下降问题.文末也给各位留下了解决方案--日志级别动态调整. 本文将详细介绍& ...

  6. 华南理工大学 Python第7章课后小测-1

    1.(单选)以下程序对字典进行排序,按字典键值从小到大排序,空白处的代码是(  ): dt={'b':6, 'c':2, 'a':4} s=sorted(dt.items(),key=_____) p ...

  7. Python 第四次实验

    1.(程序设计)定义函数def GetRandomChar(),返回一个随机的数字或大写或小写字母,每个符号出现的机会相等.调用该函数8次,生成并输出一个8位的验证码.用户输入该验证码,如果验证码正确 ...

  8. 4.Ceph 基础篇 - 对象存储使用

    文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247485256&idx=1&sn=39e07215 ...

  9. Logstash:input plugin 介绍

  10. rpm,docker,k8s三种方式安装部署GitLab服务

    rpm方式 源地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ wget https://mirrors.tuna.tsinghua ...