小 C 爱观察(observe)

news2024/11/18 9:49:37

小 C 爱观察(observe)

  • 题目描述
  • 输入格式
  • 输出格式
  • 样例
    • 输入数据#1
    • 输出数据#1
    • 解释#1
    • 输入数据#2
    • 输出数据#2
    • 输入数据#3
    • 输出数据#3

题目描述

小 C 非常喜欢树。上次后院的蚂蚁看腻了,这次准备来观察树。

小 C 每天起得早早的,给小树浇水,并且每天记录这棵小树的一些数据。树在小 C 的精心呵护下不断长大。经过若干天的记录,小 C 竟然发现了一棵树生长的规律!

为了阐述其规律,小 C 想先使用一种严谨的语言来抽象化一棵树。

首先,小 C 用图论的概念定义了一棵树 T = < V , E > T =< V,E > T=<V,E> V V V 表示所有点构成的集合, E E E 表示所有边(无向边)构成的集合。一棵具有一定形态的树用一个大写字母简记,一般会使用 T T T;其大小等于 ∣ V ∣ |V| V,即节点的个数。

小 C 发现所有树都有一个共同点:大小为 n n n 的树,恰好含有 n − 1 n − 1 n1 条边,并且任意两个节点间存在路径使得互相可达。比如说下图中 (A) 是一棵树,而 (B)© 却不是。

自然界中所有树都有根,对于树 T T T 也有且仅有一个根,其为 V V V 中的某个节点 r r r。于是 小 C 可以对所有节点定义深度,节点 u u u 的深度等于 u u u r r r 的距离 + 1 +1 +1,例如下面这棵树中,令节点 1 1 1 为根 r r r,则节点 2 2 2 3 3 3 的深度为 2 2 2,节点 4 4 4 5 5 5 的深度为 3 3 3,而节点 1 1 1 自身的深度为 1 1 1

由此可以看出,抽象出来的树和现实中的树正好上下颠倒了。接下来小 C 开始定义生长。某次生长操作用 T = g r o w ( T ’ , d ) T = grow(T’,d) T=grow(T,d) 表示, T ’ T’ T表示生长前的树, T T T 表示生长之后的树。 成长规律根据参数 d d d 决定。生长时, T ’ T’ T中所有深度为 d d d 的节点同时增加一个新的节点与之连接,得到的树即为 T T T。比如说下图中 (A) 为原树 T T T,(B) 为 g r o w ( T , 1 ) grow(T,1) grow(T,1),© 为 g r o w ( T , 2 ) grow(T,2) grow(T,2)

小 C 又定义成长,表示一棵树经过一系列生长得到另一棵树的过程。令原树为 T 0 T_0 T0​ , 总共 k k k 次生长操作,第 i i i 次生长的参数为 d i d_i di ,则可以表示为:

T 1 = g r o w ( T 0 , d 1 ) → T 2 = g r o w ( T 1 , d 2 ) → ⋅ ⋅ ⋅ → T k = g r o w ( T k − 1 , d k ) T_1 = grow(T_0 ,d_1 ) → T_2 = grow(T_1 ,d_2 ) → ··· → T_k = grow(T_{k−1} ,d_k ) T1=grow(T0,d1)T2=grow(T1,d2)⋅⋅⋅Tk=grow(Tk1,dk)
小 C 又定义种子为大小为 11、仅包含根节点的树。下图是一颗种子的成长过程。

然而一个猜想需要诸多事实来支撑。小 C 又观察了许多棵树,然而树儿都长大了,小 C 只能得到成长之后的树 T T T。他想知道对于一颗种子,存不存在某种成长过程,使得种子 能长成树 T T T。于是小 C 把问题交给了你。

本题每个输入文件有多组测试数据

输入格式

从文件 observe.in 中读取数据。 第一行一个正整数 Q Q Q,表示数据组数。

对于每组数据,将会描述一棵成长之后的树 T T T

每组数第一行两个正整数 n n n r r r,表示树 T T T 的大小、 T T T 的根,节点依次从 1 1 1 n n n 标号;

接下来 n − 1 n − 1 n1 行,每行两个整数 u u u v v v,描述一条边 ( u , v ) (u,v) (u,v)

保证 T T T 一定是一棵合法的树。

输出格式

输出到文件 observe.out 中。 总共 Q Q Q 行,每行表示对应的树 T T T 是否存在成长过程,使得种子成长成 T T T,如果存在, 输出 Yes,否则输出 No(请注意大小写)。

样例

输入数据#1

1
6 1
1 2
1 3
2 4
2 5
3 6

输出数据#1

Yes

解释#1

这棵树的形态如下。

此为题面描述的成长过程中的例子。

输入数据#2

1
6 1
1 2
2 3
3 4
1 5
5 6

输出数据#2

No

解释#2
这棵树的形态如下。

一颗种子不存在某种成长方式变成这棵树。

输入数据#3

2
6 1
1 2
1 3
2 4
2 5
3 6
6 1
1 2
2 3
3 4
1 5
5 6

输出数据#3

Yes
No

样例4-5
请下载附件查看(附件)。

数据范围
对于 10 % 的数据: n ≤ 5 。 对于 10\% 的数据:n≤5。 对于10%的数据:n5
对于 30 % 的数据: n ≤ 10 。 对于 30\% 的数据:n≤10。 对于30%的数据:n10
对于 50 % 的数据: n ≤ 100 。 对于 50\% 的数据:n≤100。 对于50%的数据:n100
对于 70 % 的数据: n ≤ 3 × 1 0 3 。 对于 70\% 的数据:n≤3×10^3 。 对于70%的数据:n3×103
对于 100 % 的数据: 1 ≤ Q ≤ 10 , 1 ≤ n ≤ 1 0 5 1 ≤ r ≤ n 。 对于 100\% 的数据:1 ≤ Q ≤ 10,1 ≤ n ≤ 10^51≤r≤n。 对于100%的数据:1Q101n1051rn

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
struct node{
    vector<int> cls;
    int p;
    int n1,n2;//n1表示孩子结点数,n2表示孩子中的叶子结点数
}trees[N];
vector<int> deeps[N];//树结点深度
int nums[N];//标记深度为i的叶子结点数
priority_queue<int,vector<int>,greater<int> > ns;//小根堆,元素小的优先级高,注意这里的写法都是固定的
 
void dfs(int root,int d){
    for (int i = 0; i < trees[root].cls.size() ; ++i) {
        dfs(trees[root].cls[i], d+1);
    }
    //叶子结点
    if(trees[root].cls.empty()){
        trees[trees[root].p].n2++;//父结点的叶子结点数++
        nums[d]++;//标记深度为d的叶子结点数
        if(nums[d] == 1){//首次放入优先队列中
            ns.push(d);//按叶子优先级
        }
    }else{//非叶子结点加入deeps中
        deeps[d].push_back(root);
    }
} 
 
int main(){
    freopen("observe.in","r",stdin);
    freopen("observe.out","w",stdout); 
    int q;
    scanf("%d",&q);
    while (q--){
        int n,r;
        scanf("%d%d",&n,&r);
        memset(trees,0, sizeof(trees));
        memset(deeps,0, sizeof(deeps));
        memset(nums,0, sizeof(nums));
        ns = priority_queue<int,vector<int>,greater<int> > ();
 
        int u,v;
        for (int i = 1; i <= n - 1 ; ++i) {//n-1条边
            scanf("%d%d",&u,&v);
            trees[u].cls.push_back(v);
            trees[v].p = u;
            trees[u].n1 ++ ;
        }
        dfs(r,1);
        if(nums[n]){//说明是单链
            printf("Yes\n");
            continue;
        }
        while(!ns.empty()){
            int d = ns.top();//叶子结点深度是d,需要从d-1层结点开始删除
            int size = deeps[d - 1].size();
 
            if(size > nums[d]){//如果父结点数比当前的子结点数多,肯定不满足条件,直接输出No
                printf("No\n");
                break;
            }
            vector<int> newleaf;
 
            int flag = 0;
            for (int i = 0; i < deeps[d - 1].size(); ++i) {
                int x = deeps[d - 1][i];
                if(!trees[x].n2){//某个结点没有叶子结点,不满足条件
                    flag = 1;
                    break;
                }else{
                    trees[x].n1 --;
                    trees[x].n2 --;
 
                    if(x != r && trees[x].n1 == 0){//变成了叶子结点了,先缓存起来,注意 根结点不用管了
                        newleaf.push_back(i);//记录下标,防止遍历复杂度
                    }
                }
            }
            if(flag){
                printf("No\n");
                break;
            }
            if(size == nums[d]){
                ns.pop();
            }
            nums[d] -= size;//剪去叶子结点
            //处理新产生的叶子结点
            for (int i = newleaf.size() - 1; i >= 0 ; i--) {
                nums[d-1] ++ ;
                if(nums[d-1] == 1){
                    ns.push(d-1);//产生了新深度的叶子
                }
                int t = newleaf[i];
                int q = deeps[d-1][t];
 
                trees[trees[q].p].n2 ++ ;
                //对应deeps 要 删除该结点
                deeps[d-1].erase(deeps[d-1].begin() + t);
//                for (int j = 0; j < deeps[d-1].size() ; ++j) {
//                    if(deeps[d-1][j] == t){//该元素已经变为叶子了,删除
//                        deeps[d-1].erase(deeps[d-1].begin() + j);
//                        break;
//                    }
//                }
            }
        }
        if(ns.empty()){
            printf("Yes\n");
        }
    }
    return 0;
}

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

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

相关文章

shell 流程控制之条件判断及案例

目录 流程控制之条件判断 一&#xff0c;if条件语句的语法及案例 1&#xff0c;单分支结构 2&#xff0c;双分支结构 3&#xff0c;多分支结构 二&#xff0c;复合指令 三&#xff0c; exit退出程序 四&#xff0c; 多条件判断语句case 流程控制之条件判断 条件判断语句…

【SpringCloud】Sentinel 之隔离与降级

一、上集回顾上级文章地址&#xff1a;【SpringCloud】Sentinel 之流量控制_面向架构编程的博客-CSDN博客上一篇文章我们讲解了Sentinel 流量控制、流控效果、热点参数限流的用法&#xff0c;统称为限流&#xff0c;它是一种预防措施&#xff0c;可以尽量避免因高并发而引起的服…

根据官方文档详细说明 Kubernetes 网络流量走向,包含详细的图文说明和介绍

根据官方文档详细说明 Kubernetes 网络流量走向&#xff0c;包含详细的图文说明和介绍。 阅读本文&#xff0c;你可以了解在 Kubernetes 内外&#xff0c;数据包是如何转发的&#xff0c;从原始的 Web 请求开始&#xff0c;到托管应用程序的容器。 Kubernetes 网络要求 在深入…

【three.js】本地搭建Threejs官方文档网站 解决threejs官方文档打开过慢得到问题

本文主要为了解决three.js 官方文档 打开过慢的问题 因为Three.js官网是国外的服务器&#xff0c;所以为了方便学习和快速的查阅文档&#xff0c;我们可以自己搭建Three.js官网和文档&#xff0c;方便随时查看案例和文档内容进行学习。 1、首先进入threejs库GitHub地址&#xf…

如何成为一名FPGA工程师?需要掌握哪些知识?

我国每年对于FPGA设计人才的需求缺口很大。在需求缺口巨大的情形下&#xff0c;发展前景相对可观。那么如何成为一名FPGA工程师&#xff1f; 什么是FPGA&#xff1f; FPGA&#xff08;FieldProgrammable Gate Array&#xff09;&#xff0c;即现场可编程门阵列&#xff0c;它…

新手入门Pinia

什么是Pinia Pinia 是 Vue 的专属状态管理库&#xff0c;它允许你跨组件或页面共享状态。它和Vuex作用类似(发音为 /piːnjʌ/),官网 为什么要使用Pinia 与 Vuex 相比&#xff0c;Pinia 不仅提供了一个更简单的 API&#xff0c;也提供了符合组合式 API 风格的 API&#xff0…

vue项目创建

前提&#xff1a;node安装&#xff1a;02node安装_哔哩哔哩_bilibili 1. 查看node版本 查看node版本 node -v 查看npm 版本 npm -v 2. 输入cmd 用管理员打开控制台 3. 设置淘宝镜像 npm config set registry https://registry.npm.taobao.org 4. 安装vue脚手架 npm install -g …

北大青鸟昌平校区:2023年云计算发展趋势!

云计算的大规模应用一直是许多最具变革性技术——如人工智能、物联网等的关键驱动力&#xff0c;未来也将进一步推动虚拟现实和增强现实(VR/AR)、元宇宙、甚至量子计算等技术的发展。近日&#xff0c;在美国《福布斯》网站报道中&#xff0c;列出了2023年云计算领域的五大主要趋…

56.Isaac教程--ROS

ROS ISAAC教程合集地址文章目录ROS安装ROS创建和使用自定义 ROS 包创建 ROS BridgeRos节点时间同步器消息转换器基地姿势同步自定义小码示例&#xff1a;将 ROS 导航堆栈与 Isaac 结合使用在此示例上构建将 Isaac 映射转换为 ROS 映射Isaac 和机器人操作系统 (ROS) 都使用消息传…

other-chatGPT记录

title: other-chatGPT记录 categories: Others tags: [人工智能, ai, 机器人, chatGPT] date: 2023-02-02 10:04:33 comments: false mathjax: true toc: true other-chatGPT记录 前篇 官网 https://openai.com/api - https://openai.com/api/测试 - https://platform.openai.…

DSP_CCS7实现变量的导出与MatLAB读取

前言 最近在做基于dsp平台的无通信接口系统辨识&#xff0c;因此需要直接利用CCS将数据导出&#xff0c;然后再利用MatLAB解析读取后的数据。MatLAB的代码参考了以下这篇链接: -/导出CCS3.3数据及使用matlab处理的方法.md at master dailai/- GitHub 高版本的CCS&#xff…

GitHub访问问题与 Steam++下载及使用(适合小白)

前言 &#x1f4dc; “ 作者 久绊A ” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴 ​ 目录 前言 一、Steam的介绍 1、大概介绍 2、详细介绍 二、Ste…

Unity与Android交互(双端通信)

前言 最近小编开始做关于手部康复的项目&#xff0c;需要Android集成Unity&#xff0c;以Android为主&#xff0c;Unity为辅的开发&#xff1b;上一篇给大家分享了Unity嵌入Android的操作过程&#xff0c;所以今天想给大家分享一下双端通信的知识&#xff1b; 一. Android与Un…

安装OpenResty

安装OpenResty 1.安装 首先你的Linux虚拟机必须联网 1&#xff09;安装开发库 首先要安装OpenResty的依赖开发库&#xff0c;执行命令&#xff1a; yum install -y pcre-devel openssl-devel gcc --skip-broken2&#xff09;安装OpenResty仓库 你可以在你的 CentOS 系统中…

物联网平台+业务平台基本架构设计与优化想法

前言 目前的交付底座有点老&#xff0c;而且集成的有点杂&#xff0c;计划是要升级下&#xff0c;先说想法&#xff0c;看领导做不做。 1 业务平台定位 我们的愿景&#xff1a;通过物联平台赋能&#xff0c;让数据产生价值。 为客户提供可视化的平台&#xff08;数据价值…

【王道数据结构】第二章 | 线性表

目录 2.1线性表的定义 2.2线性表的基础操作 2.3顺序表的定义 2.4顺序表的基本操作 2.5 线性表的链式表示 2.1线性表的定义 线性表是具有相同数据类型的n(n>0)个数据元素的有限序列&#xff0c;其中n为表长&#xff0c;当n0时线性表是一个空表。若用L命名线性表&#xf…

Block底层原理读书笔记-《高级编程- iOS与OS多线程和内存管理》(更新中)

1 一个Block 真正的底层都有些什么&#xff1f; Block会被解析成一个结构体&#xff08;这里成为Block结构体&#xff09;&#xff0c;这个结构体里有&#xff1a; &#xff08;1&#xff09;isa指针&#xff08;说明Block的本质是一个对象&#xff09;&#xff1a;指向Stack…

动态修改Azure DevOps区域路径或迭代路径的继承权限(Inhertiance)

Contents1. 场景描述2. 解决方案2.1 更改继承的接口&#xff1a;ChangeInhertiance2.2 获取区域路径的接口&#xff1a;ClassificationNodes1. 场景描述客户使用工作项模板&#xff0c;定制了一个设计变更流程&#xff0c;需要在不同的阶段(流程状态)控制工作项的更改权限。我们…

Grafana 系列文章(六):Grafana Explore 中的日志

&#x1f449;️URL: https://grafana.com/docs/grafana/latest/explore/logs-integration/#labels-and-detected-fields &#x1f4dd;Description: Explore 中的日志 除了指标之外&#xff0c;Explore 还允许你在以下数据源中调查你的日志。 ElasticsearchInfluxDBLoki 在基…

[算法设计与分析考点4] 改进的串匹配算法——KMP算法

算法核心思想 在BF算法的基础上加以改进&#xff0c;BF算法中每次当前字符不相等时&#xff0c;主串S要回溯到其下一个字符处&#xff0c;模式串T要回溯到 j0 位置进行下一趟的匹配。然而&#xff0c;大多数情况下&#xff0c;这种回溯是没有必要的&#xff0c;非常耗时且效率低…