普通树转二叉树

2023-10-26

【实现方法】

对于普通树转二叉树,要记住6个字口诀:左儿子,右兄弟

实现的步骤是这样的:

  1. 将树的根节点直接作为二叉树的根节点
  2. 将树的根节点的第一个子节点作为根节点的左儿子,若该子节点存在兄弟节点,则将该子节点的第一个兄弟节点(方向从左往右)作为该子节点的右儿子
  3. 将树中的剩余节点按照上一步的方式,依序添加到二叉树中,直到树中所有的节点都在二叉树中

其实说白了就是每个点的左儿子是它的第一个儿子,右儿子是它从左往右数的第一个兄弟

如下图所示(可以自己画一画理解一下):

 

还可以这样理解普通树转换成二叉树(实际上是一样的):

  1. 在所有兄弟结点之间加一连线
  2. 对每个结点,除了保留与其第一个儿子的连线外,去掉该结点与其它孩子的连线

如下图所示:

这样一来,就能使一些问题(例如树形DP)更好做一点

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=105;
int son[N],left[N],right[N];
int main()
{
	int n,i,x,y;
	scanf("%d",&n);          //表示有n个点 
	for(i=1;i<=n;i++)
	{
	    scanf("%d",&x);      //x是i号节点的父亲 
    	    if(!son[x])  left[x]=i;      //这两步就是根据左儿子右兄弟的方式转二叉树 
    	    else  right[son[x]]=i;
    	    son[x]=i;
	}
	for(i=1;i<=n;++i)
	  printf("%d %d\n",left[i],right[i]);
	return 0;
}

 

【例题】

例题传送门选课

题目大意:有N门功课,每门课有个学分,每门课有0或1门先修课(若课程a是课程b的先修课,那么只有学完了课程a,才能学习课程b)。现要选择M门课程,求最大的学分(洛谷 P2014)

这道题可以把它当做树形DP来做,首先,每个节点的父亲节点是它的先修课,虚建一个节点连向先修课,然后把它转换成二叉树来做,就和二叉苹果树那道题差不多了

不过要注意的是转移的时候有一些差别

要学第x门课和以它为先修课的课:f[x][y]=max(f[x][y],dp(son[x],i)+dp(bro[x],y-i-1)+a[x]);

不学第x门课,全部学它兄弟的课程:f[x][y]=max(f[x][y],dp(bro[x],y));

那么直接用树形DP就行了

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=305;
int n,m;
int a[N],bro[N],son[N],f[N][N];
int dp(int x,int y)
{
	if(x==-1||y==0)  return 0;
	if(f[x][y])  return f[x][y];
	int i;
	f[x][y]=max(f[x][y],dp(bro[x],y));
	for(i=0;i<=y-1;++i)
	  f[x][y]=max(f[x][y],dp(son[x],i)+dp(bro[x],y-i-1)+a[x]);
	return f[x][y];
}
int main()
{
	int x,i;
	memset(son,-1,sizeof(son));
	memset(bro,-1,sizeof(bro));
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
	{
	    scanf("%d%d",&x,&a[i]);
    	    bro[i]=son[x];
    	    son[x]=i;
	}
	dp(0,m+1);
	printf("%d",f[0][m+1]);
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

普通树转二叉树 的相关文章

  • 群晖nas上部署gitea后修改IP地址

    事件 今天 我在nas的套件中心中发现了Gitea这个套件 想到自己的代码都是保存在GitHub或者Gitee上面的 于是乎我边在nas上面装了这个套件 装备将代码在nas里面也备份一份 我的nas所在网络没有公网IP 用内网穿透形式弄的

随机推荐

  • JAVA学习笔记(1)与日期相关的类相关知识记录

    介绍Java涉及日期的类 Date类 获取日期对象 Calendar类 获取日期的特定部分 时分秒 Date类 构造函数 一共有两个构造函数Date 使用当前日期和时间初始化对象 Date long millisec 接受一个参数 该参数是
  • Leetcode 刷题笔记(三) —— 数组类型解题方法三:滑动窗口

    文章目录 系列文章目录 题录 209 长度最小的子数组 904 水果成篮 76 最小覆盖子串 困难 总结 系列文章目录 一 数组类型解题方法一 二分法 二 数组类型解题方法二 双指针法 三 数组类型解题方法三 滑动窗口 四 数组类型解题方法
  • 多线程、异步爬取数据(优化篇)

    爬虫优化 一般方法 多线程 异步 scrapy框架 理解要点 scrapy文件目录 middleware py jd refer py item py pipeline py debug py 一般方法 京东商品数据爬取 91 403s p
  • DOS操作命令

    DOS操作命令 1 cleanmgr 打开磁盘清理工具 2 compmgmt msc 计算机管理 3 conf 启动系统配置实用程序 4 charmap 启动字符映射表 5 calc 启动计算器 6 chkdsk exe Chkdsk磁盘检
  • 如何检测手机当前为“桌面”(desktop)状态

    介绍 一些桌面软件会在用户把手机切换到桌面 desktop 时显示一些特定的信息 如图片 滚动文字等 达到一种个性桌面的效果 这里就介绍一种检测 桌面 的方法 S60 2nd的 桌面 是电话应用 S60 3rd的 桌面 是Idle exe
  • 声明式事务源码解析--- Spring源码从入门到精通(二十六)

    上篇文章介绍了事务代码的实例 声明式事务 Spring源码从入门 到精通 二十五 这篇文章主要介绍事务源码解析 一 EnableTransactionManagerment 里面import一个TransactionManagementCo
  • 【RDMA】技术详解(一):RDMA概述

    目录 0 前言 一 技术背景 1 传统的 TCP IP 网络通信的弊端 2 新的网络通信技术 TOE and RDMA 2 1 TOE TCP IP协议处理工作从CPU转移到网卡 2 2 RDMA 绕过CPU 数据直接 传 到对端内存 二
  • linux命令 uname -r 和 uname -a 的详解

    1 uname r 显示操作系统的发行版号2 uname a 显示系统名 节点名称 操作系统的发行版号 内核版本等等 系统名 Linux 节点名称 qyw 操作系统的发行版号 3 10 0 957 21 3 el7 x86 64 命名规则
  • Nginx负载均衡session会话保持方法

    负载均衡时 为了保证同一用户session会被分配到同一台服务器上 可以使用以下方法 1 使用cookie 将用户的session存入cookie里 当用户分配到不同的服务器时 先判断服务器是否存在该用户的session 如果没有就先把co
  • Java 秒杀方案(下)

    技术点 前端 Thymeleaf Bootstrap Jquery 后端 SpringBoot MyBatisPlus Lombok 中间件 Redis RabbitMQ 秒杀方案简介 本短文完成项目搭建 分布式 Session 和秒杀功能
  • Linux DDR3寻址地址映射

    1 相关原理 DDR3内部相当于存储表格 和表格的检索相似 需要先指定 行地址 row 再指定列地址 column 这样就可以准确的找到需要的单元格 对于DDR3内存 单元格称为基本存储单元 也就是每次能从该DDR3芯片读取的最小数据 存储
  • C语言编译过程详解

    前言 C语言程序从源代码到二进制行程序都经历了那些过程 本文以Linux下C语言的编译过程为例 讲解C语言程序的编译过程 编写hello world C程序 hello c include
  • 【mmYOLO】促进视觉项目落地,主打工程经验和实用。从原理配置到属性设置,从模型训练到模型评测

    MMYOLO 是一个基于 PyTorch 和 MMDetection 的 YOLO 系列算法开源工具箱 它是 OpenMMLab 项目的一部分 目前支持的任务有目标检测 旋转框目标检测 具有如下三个特性 统一便捷的算法评测 MMYOLO 统
  • MYSQL 根据不同字段的汇总相同字段的总数

    需求 汇总一个用户不同支付方式的购买的总杯数 buy num 杯数 pay code 支付方式 pay name 支付名称 pay status 支付状态 ms order 订单表 ms user 用户表 SELECT u id pay n
  • 微信小程序开发之视频video组件报错:渲染层网络层错误

    微信小程序开发之视频video组件报错 渲染层网络层错误 视频正常播放 暂停 使用正常 但报错 From server 61 147 235 115 console error VM1074 1 anonymous VM1101 2 VM1
  • LCP概念

    http blog csdn net zzfcnc article details 6660456 对于PPP协议 可以讲解的内容非常多 这个协议的应用也非常的广泛 那么这里我们就重点讲解一下LCP的内容 首先我们需要来哦接一下ppp协议的
  • python实现跨excel的工作表sheet之间的复制

    python 将test1的Sheet1通过 跨文件 复制到test2的Sheet2里面 包括谷歌没有能搜出这种问题答案 我们贴出代码 我们加载openpyxl这个包来解决 from openpyxl import load workboo
  • 【数据库 Mysql查询系列】--检索出stu表中‘计算机工程’或‘软件工程’专业的学生的记录,结果集按学号升序排序。

    涉及到的两个表 代码如下 select sno as 学号 sname as 姓名 sex as 性别 mname as 专业 from stu major where stu mno major mno and mname in 计算机工
  • nodejs快速上手编写程序

    module export 和 exports 的区别 根本上的区别 exports 返回的是模块函数 module exports 返回的是模块对象本身 返回的是一个类 使用上的区别是 exports 的方法可以直接调用 module e
  • 普通树转二叉树

    实现方法 对于普通树转二叉树 要记住6个字口诀 左儿子 右兄弟 实现的步骤是这样的 将树的根节点直接作为二叉树的根节点 将树的根节点的第一个子节点作为根节点的左儿子 若该子节点存在兄弟节点 则将该子节点的第一个兄弟节点 方向从左往右 作为该