hihocoder-1453-Rikka with Tree

Posted zhang--yd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihocoder-1453-Rikka with Tree相关的知识,希望对你有一定的参考价值。

 

#Hihocoder 1453 : Rikka with Tree

时间限制:10000ms
单点时限:1000ms
内存限制:256MB
 
source: https://hihocoder.com/problemset/problem/1453

描述

众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的:

勇太有一棵 n 个节点的以1为根的有根树。现在他可以对这棵树进行若干次操作,每一次操作可以选择树上的一个点然后删掉这个点和它的儿子之间的所有边。

现在勇太想要知道对于每一个 k ∈ [1, n],最少需要多少次操作才能让图中恰好存在 k 个联通块。

当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?

输入

第一行输入一个正整数 n (n ≤ 3000)。

第二行输入 n-1 个整数 fi 表示 i+1 号点的父亲,保证 1 ≤ fi ≤ i

输出

输出 n 个整数,第 i 个数表示 k=i 时的答案,如果无法让图中恰好存在 k 个联通块,则输出-1。

样例输入
6
1 2 1 1 2
样例输出
0 -1 1 1 -1 2

 

题解:

每减去一个节点,产生的联通块的数量就是该节点的孩子数量。  所以, 实质上是一道单重背包问题的变形。 

 

#include <iostream> 
#include <cstdio> 
#include <cstring> 
#include <cstdlib> 
using namespace std; 
const int MAXN = 3005; 

int n, root[MAXN], dp[MAXN]; 

int main(){
	freopen("in.txt", "r", stdin);

	int x, max_x, tmp; 
	scanf("%d", &n);
	memset(root, 0, sizeof(root));  
	max_x = 0; 
	for(int i=1; i<n; ++i) {
		scanf("%d", &x); 
		root[x]++;  
		if(max_x < x){
			max_x = x; 
		}
	}
	memset(dp, 0, sizeof(dp)); 
	dp[0] = 1; 
	for(int i=max_x; i>=1; --i){
		if(root[i] != 0){
			for(int j=n; j>=root[i]; --j){
				if(dp[j-root[i]] != 0){
					if(dp[j] != 0){
						dp[j] = min(dp[j], dp[j-root[i]] + 1); 
					}  else {
						dp[j] = dp[j-root[i]] + 1; 
					}
				}
			}
		}
	}
	for(int i=0; i<n; ++i){
		if(dp[i]){
			printf("%d ", dp[i]-1);
		}else{
			printf("%d ", -1 );
		}
	}
	printf("\n");

	return 0; 
}

  

以上是关于hihocoder-1453-Rikka with Tree的主要内容,如果未能解决你的问题,请参考以下文章

with的用法

在 SQL 中是不是可以在 WITH 中使用 WITH

SQL:with 查询

mac 下完全安装 ffmpeg

SQL 中with的用法

with as 用法