题面

CF429C Guess the Tree

给一个长度为 \(n\) 的数组 \(a_i\),问是否有一棵树,每个节点要么是叶子要么至少有两个儿子,而且 \(i\) 号点的子树大小是 \(a_i\)。

数据范围:\(1\le n\le 24\)。


题解

发现 \(n\) 很小,想到可以状压。

设叶子节点有 \(ln\) 个,所以中间节点有 \(mn=n-ln\) 个。

由于“每个节点要么是叶子要么至少有两个儿子”,所以 \(ln\ge\lceil\frac n2\rceil\),\(mn\le n-\lceil\frac n2\rceil \le 11\)。

所以可以先特判 \(2mn\ge n\) 的情况答案为 NO

然后剩下的可以 dp设 \(f_{t,s,i}\):

\(t\) 表示是一棵森林还是一个子树(为了对付“每个节点要么是叶子要么至少有两个儿子”,如果是子树 \(t=0\),否则 \(t=1\))。

\(s\) 表示包含的中间节点集合,\(s< 2^{mn}\le 2048\)。

\(i\) 表示包含的叶子节点个树,因为叶子节点都是一样的,所以这样可以优化状压。

值表示是否存在这样的森林,如果存在 \(=1\),否则 \(=0\)。

考虑怎么转移:

  1. 一棵森林(子树)和另一棵森林(子树)合并成新的森林。

  2. 一棵森林上面加一个 \(a=\) 森林大小 \(+1\) 的节点成为一棵子树(怎么求一棵森林的大小?其实就是 \({\rm popcount}(s)+i\) 啦)。

然后就剩初始化的问题了,因为 \(i\) 这维就像一个背包,而且因为 \(s\) 这一维保证不会有重点,所以可以在 dp 中用无限背包的方式,这样就只需要初始化 \(f_{0,0,1}=1\) 了。

时间复杂度 \(\Theta(ln^2 3^{mn})\),细节看代码。


代码

#include <bits/stdc++.h>
using namespace std; //Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair((a),(b))
#define x first
#define y second
#define bg begin()
#define ed end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define R(i,a,b) for(int i=(a),i##E=(b);i<i##E;i++)
#define L(i,a,b) for(int i=(b)-1,i##E=(a)-1;i>i##E;i--)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f; //Data
const int N=24,mN=11;
int n,sn,ln,mn,a[N],b[1<<mN];
int f[2][1<<mN][N+1]; // 森林还是子树,中间节点集,叶子节点数
bool get(int s,int i){ // 返回 f[1][s][i] 的值
for(int su=s;su;su=s&(su-1))if(!(su&(s^su)))R(j,0,i+1)
if((f[0][su][j]||f[1][su][j])&&(f[0][s^su][i-j]||f[1][s^su][i-j])) return true;
R(j,0,i+1)if((f[0][0][j]||f[1][0][j])&&(f[0][s][i-j]||f[1][s][i-j])) return true; // 因为 su!=0,补上循环中缺少的 su=0
return false;
} //Main
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n; R(i,0,n) cin>>a[i]; sort(a,a+n,greater<int>());
R(i,0,n)if(a[i]>1) mn++; ln=n-mn,sn=1<<mn,sort(a,a+mn);
if(mn*2>=n) cout<<"NO\n",exit(0);
R(i,1,sn) b[i]=b[i>>1]+(i&1);
f[0][0][1]=true;
R(s,0,sn)R(i,0,ln+1)if(get(s,i)){
f[1][s][i]=true;
R(t,0,mn)if(!(s&(1<<t))&&a[t]==b[s]+i+1) // 加新的 a= 森林大小+1 的节点形成子树
f[0][s^(1<<t)][i]=true;
}
if(f[0][sn-1][ln]) cout<<"YES\n";
else cout<<"NO\n";
return 0;
}

祝大家学习愉快!

题解-CF429C Guess the Tree的更多相关文章

  1. 题解:CF593D Happy Tree Party

    题解:CF593D Happy Tree Party Description Bogdan has a birthday today and mom gave him a tree consistin ...

  2. 题解-AtCoder Code-Festival2017 Final-J Tree MST

    Problem \(\mathrm{Code~Festival~2017~Final~J}\) 题意概要:一棵 \(n\) 个节点有点权边权的树.构建一张完全图,对于任意一对点 \((x,y)\),连 ...

  3. PAT甲题题解-1110. Complete Binary Tree (25)-(判断是否为完全二叉树)

    题意:判断一个节点为n的二叉树是否为完全二叉树.Yes输出完全二叉树的最后一个节点,No输出根节点. 建树,然后分别将该树与节点树为n的二叉树相比较,统计对应的节点个数,如果为n,则为完全二叉树,否则 ...

  4. [LeetCode 题解]: Validate Binary Search Tree

    Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...

  5. leetcode题解:Construct Binary Tree from Inorder and Postorder Traversal(根据中序和后序遍历构造二叉树)

    题目: Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume ...

  6. 题解 CF383C 【Propagating tree】

    这道题明明没有省选难度啊,为什么就成紫题了QAQ 另:在CF上A了但是洛谷Remote Judge玄学爆零. 思路是DFS序+线段树. 首先这道题直观上可以对于每一次修改用DFS暴力O(n),然后对于 ...

  7. 题解 [CF916E] Jamie and Tree

    题面 解析 这题考试时刚了四个小时. 结果还是爆零了 主要就是因为\(lca\)找伪了. 我们先考虑没有操作1,那就是裸的线段树. 在换了根以后,主要就是\(lca\)不好找(分类讨论伪了). 我们将 ...

  8. 题解 【HEOI2016】tree树

    题面 解析 其实这题可以考虑离线做法,用并查集解决. 因为仔细想,添加标记并不方便, 但如果用并查集记录下祖先, 再一一删除,就会方便很多. 先把每次操作记录下来, 同时记录下每个点被标记的次数(因为 ...

  9. 题解-hzy loves segment tree I

    Problem 题目概要:给定一棵 \(n\) 个节点的树,点有点权,进行 \(m\) 次路径取\(\max\)的操作,最后统一输出点权 \(n\leq 10^5,m\leq 5\times 10^6 ...

随机推荐

  1. mysql一些好的问题

    一."N叉树"的N值在MySQL中是可以被人工调整吗? 1, 通过改变key值来调整N叉树中非叶子节点存放的是索引信息,索引包含Key和Point指针.Point指针固定为6个字节 ...

  2. TextView之富文本

    项目中使用富文本比较常见了,一行显示多种样式颜色的文本,使用 ClickableSpan 富文本实现在同一个 TextView 中的文本的颜色.大小.背景色等属性的多样化和个性化. 我们也可以使用Ht ...

  3. 六:Redis配制文件

    1.它在哪儿 1.1 安装包解压开里面就会有redis.conf 1.2 我们在修改一定要拷贝一份,修改拷贝的那一份 2.Units单位 2.1 对于单位来说配制开头定义了,1k和1kb是不一样的,同 ...

  4. 洛谷 P2101 命运石之门的选择 (分治)

    P2101 命运石之门的选择 (分治) 介绍 El Psy Congroo 题目链接 没错,作为石头门厨,怎么能不做石头门的题呢?(在搜石头门的时 候搜到了本题) 本题作为一道分治基础练习题还是不错的 ...

  5. OMV openmediavault NAS系统命令显示颜色

    闲鱼65f元买的我家云刷了OMV系统. 但ls命令查看文件不显示颜色. cd /etc/进入配置文件目录查看并没有bashrc文件,但有个bash.bashrc 在 bash.bashrc后面加入以下 ...

  6. Linux Shell操作 执行C代码显示当前路径

    在unix系统下一切皆文件,文件夹是文件的一种.设备也会对应到相应的文件类型. 基础知识: . 代表当前路径 ..代表上级目录(父目录) / 在路径的最前边的时候代表树根.在路径中间的时候只不过是路径 ...

  7. C#设计模式-外观模式(Facade Pattern)

    引言 在软件测试中,一般都是在功能测试稳定的情况下再进行UI自动化测试.或者进行性能测试.如果一个一个进行太麻烦,此时可以使用对外提供一个简单接口,通过这个接口可以访问内部一群接口.例如进行UI自动化 ...

  8. java后端开发三年!你还不了解Spring 依赖注入,凭什么给你涨薪

    前言 前两天和一个同学吃饭的时候同学跟我说了一件事,说他公司有个做了两年的人向他提出要涨薪资,他就顺口问了一个问题关于spring依赖注入的,那个要求涨薪的同学居然被问懵了...事后回家想了想这一块确 ...

  9. MAC系统网页链接如何下载

    Folx 5 是一款简单易用.功能强大的Mac OS系统的下载管理器.Folx界面简洁,下载管理方便,支持网页链接下载.BT下载和YouTube下载,而且还可以设置计划任务.搜索BT种子以及添加Tra ...

  10. 带你了解Boom 3D的Mac版音效模式

    音乐是很好的情绪抒发途径,因为音乐蕴含了很多信息,包含了很多情感,所以我们聆听不同种类的音乐的时候会产生不同的心理感受.这就是音乐的魅力,可以让人产生共鸣引发无数的思绪.为了能够更好的体会感受音乐可以 ...