[USACO11MAR]树装饰Tree Decoration

本文探讨了一个有趣的优化问题,关于如何在限定条件下,以最低成本满足每个节点特定的装饰需求。通过构建数学模型,使用动态规划算法,实现了装饰物的最优分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

Farmer John is decorating his Spring Equinox Tree (like a Christmas tree but popular about three months later). It can be modeled as a rooted mathematical tree with N (1 <= N <= 100,000) elements, labeled 1...N, with element 1 as the root of the tree. Each tree element e > 1 has a parent, P_e (1 <= P_e <= N). Element 1 has no parent (denoted '-1' in the input), of course, because it is the root of the tree.

Each element i has a corresponding subtree (potentially of size 1) rooted there. FJ would like to make sure that the subtree corresponding to element i has a total of at least C_i (0 <= C_i <= 10,000,000) ornaments scattered among its members. He would also like to minimize the total amount of time it takes him to place all the ornaments (it takes time K*T_i to place K ornaments at element i (1 <= T_i <= 100)).

Help FJ determine the minimum amount of time it takes to place ornaments that satisfy the constraints. Note that this answer might not fit into a 32-bit integer, but it will fit into a signed 64-bit integer.

For example, consider the tree below where nodes located higher on the display are parents of connected lower nodes (1 is the root):

For example, consider the tree below where nodes located higher on
the display are parents of connected lower nodes (1 is the root):

               1 
               |
               2
               |
               5
              / \
             4   3

Suppose that FJ has the following subtree constraints:

                  Minimum ornaments the subtree requires
                    |     Time to install an ornament
       Subtree      |       |
        root   |   C_i  |  T_i
       --------+--------+-------
          1    |    9   |   3
          2    |    2   |   2
          3    |    3   |   2
          4    |    1   |   4
          5    |    3   |   3

Then FJ can place all the ornaments as shown below, for a total
cost of 20:

            1 [0/9(0)]     legend: element# [ornaments here/
            |                      total ornaments in subtree(node install time)]
            2 [3/9(6)]
            |
            5 [0/6(0)]
           / \
 [1/1(4)] 4   3 [5/5(10)]

输入输出格式

输入格式:

 

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 contains three space-separated integers: P_i, C_i, and T_i

 

输出格式:

 

* Line 1: A single integer: The minimum time to place all the

ornaments

 

输入输出样例

输入样例#1: 

5 
-1 9 3 
1 2 2 
5 3 2 
5 1 4 
2 3 3 

输出样例#1: 

20 

 

翻译

约翰正在装饰他家的圣诞树。圣诞树上有个 N 个结点,第一个结点是根,其余结点都有唯一的

父亲结点,第 i 个结点的父亲是 P i 。由于根没有父亲,所以记 P 1 = −1。

约翰可以在每个结点上挂载装饰物,但费用是变化。在第 i 个结点上挂载一个装饰物需要花费 C i

元钱。奶牛对这个圣诞树上每个结点都有特殊的装饰需求,对于第 i 个结点,奶牛要求以它为根的子

树上必须有 D i 个装饰物。请问约翰在哪些结点上挂载装饰物,才能满足奶牛的要求,并且使得装饰

费用最少?

输入 • 第一行:单个整数 N,1 ≤ N ≤ 10 5

• 第二行到 N 行:第 i+1 行有三个整数:P i ,D i 和 C i ,1 ≤ P i ≤ N, 0 ≤ D i ≤ 10 6 , 1 ≤ C i ≤ 100

输出 • 单个整数,表示完成所有装饰要求的最少费用

样例输入

5 -1 9 3 1 2 2 5 3 2 5 1 4 2 3 3 样例输出

20 提示 在第四个结点上放一个,花 4 元;在第三个

结点上放五个,花 10 元;在第二个结点上放三

个,花 6 元;

 

 

题解:

记得开long long

注释在代码里面

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
const int N=1e5+10;
struct edge{//编目录 
	int v,nxt;
}e[N];int cnt,last[N];
inline void add(int u,int v){//建边 
	e[++cnt]=(edge){v,last[u]};
	last[u]=cnt;
}
struct trnode{//树形结构 
	LL cost,minn,s;//cost表示满足当前节点的要求所需的最小花费,minn表示i的子树中单价最小的节点,s为以i为根的所以节点的装饰总数, 
}tr[N];
LL d[N],c[N];
int n;
void dfs(int u){
	tr[u].minn=c[u];tr[u].s=0; 
	for(int i=last[u],v=e[i].v;i;i=e[i].nxt,v=e[i].v){//搜索所有的儿子节点,求出cost,minn和s 
		dfs(v);
		tr[u].minn=min(tr[u].minn,tr[v].minn);
		tr[u].s+=tr[v].s;
		tr[u].cost+=tr[v].cost;
	}
	LL tt=d[u]-tr[u].s;//表示还差的装饰数 
	if(tt<0)tt=0;//tt>=0 
	else tr[u].s=d[u];//不要忘记改变tr[u].s 
	tr[u].cost+=LL(tt*tr[u].minn);//增加当前节点的花费 
}
int main(){
	scanf("%lld",&n);int tt;
	for(int i=1;i<=n;i++){
		scanf("%d%lld%lld",&tt,&d[i],&c[i]);
		if(tt==-1)continue;
		add(tt,i);//建边 
	}
	dfs(1);//搜索根节点 
	printf("%lld\n",tr[1].cost);//输出 
	return 0;
}

这一道题是真的很水

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值