Decorate Apple Tree
题面翻译
题目大意
给你一个 n n n个结点以 1 1 1为根的树,给这 n n n个结点任意染色,定义一个点为快乐结点当且仅当这个结点的子树上所有点颜色均不相同。求出对于 1 ∼ n 1\sim n 1∼n中的每一个 k k k,快乐结点数大于等于 k k k所需要的最少颜色数。
输入格式
第一行一个数 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le 10^5) n(1≤n≤105),表示结点数量
第二行 n − 1 n-1 n−1个数 p i p_i pi,表示第 i i i个结点的父亲结点 ( 1 ≤ p i < i ) (1\le p_i<i) (1≤pi<i)
输出格式
一行, n n n个数,表示对于 1 ∼ n 1\sim n 1∼n中的每一个 k k k,快乐节点数大于等于 k k k时所需的最少颜色数
样例 #1
样例输入 #1
3
1 1
样例输出 #1
1 1 2
样例 #2
样例输入 #2
5
1 1 3 3
样例输出 #2
1 1 1 2 3
想不到,注意到了给定的树有多少个叶子节点就输出多少个1,最后一个数是以1为根的子树的叶子节点的最大值,然后就想不到了。
题解说,问题可以转换为以每个点为根的子树有多少叶子节点,排序就是答案。
搞不懂,知道看了别人的解释
给一棵树,能给叶子染不同的颜色,定义一个节点为happy当且仅当该子树叶子节点(可包括本身)的颜色各不相同,然后求分别有1到n个happy节点的情况下的最小颜色数
反过来想,先考虑n的情况,要n个happy节点,那就是所有叶子都染不同颜色,然后考虑n-1的情况,就去掉一个根节点,那么就变成两棵独立的子树,那只要保证那个叶子节点多的那个子树的叶子染不同的颜色即可,另外的兄弟子树的叶子不管染什么色肯定不会超过这一棵的颜色数,所以其实就是第二大的叶子数的子树,所以答案就是dfs一遍预处理出每个节点对应的子树的叶子节点数,排序输出即可
(想到的一个问题)如何求1 ~ n 中以每个点为根的最大子树的节点个数。挖坑未填
如何用带以int 作为返回值的dfs求以u为根的子树有多少叶节点?
完全等价的两种写法,我一直感觉不带返回值的要比带返回值的好写。
int dfs(int u,int fa){
bool flag = 1;
for(int i=h[u];i!=-1;i=ne[i]){
int j = e[i];
if(e[i]==fa)continue;
flag = 0;
cnt[u] += dfs(j,u);
}
if(flag){
cnt[u] = 1;
}
return cnt[u];
}
void dfs(int u,int fa){
bool flag = 1;
for(int i=h[u];i!=-1;i=ne[i]){
int j = e[i];
if(e[i]==fa)continue;
flag = 0;
dfs(j,u);
cnt[u]+=cnt[e[i]];
}
if(flag){
cnt[u] = 1;
}
}