1472. Martian Army

时间:2021-07-21 19:48:02

http://acm.timus.ru/problem.aspx?space=1&num=1472

题目大意:

一颗树,根节点(1) 的值为 1.0,所有叶子节点的值为 0.0 ,其他节点值任意

最后要求的是 所有相邻两个节点的值差的总和最小。

思路:

假设一个叶子节点为 c ,他的父节点为 b ,b的父节点为 a,那么 c 的值为 0.0,

此子树的最优结果为 (value[a]-value[b])*cost[a->b] + (value[b]-value[c])*cost[b->c] 的最小值

因为value[c]=0.0 确定,那么value[b]的值要么为 0.0 要么为value[a] 这要取决于 cost[a->b] 和 cost[b->c]

的大小关系,value[] 差值为0的那一段可以去掉,然后如果a还有其他枝叶,要累加。

然后以这种思想逐步向上递归,直到根节点。看代码可以一目了然。

刚开始一直WA9,后来把多组输入改成单组就对了,URAL上的题多数为单组数据测试,但平时写的时候为了自己测试方便

就习惯写成多组的,一般也不会出问题,这题的第9组测试数据,应该是有多余的数据在最后,所有才会出错。

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring> using namespace std; const int INF=0x3f3f3f3f;
const int N=100005;
int k[N],c[N];
int dp[N];
bool loaf[N];
int main()
{
//freopen("data.in","r",stdin);
int n;
scanf("%d",&n);
memset(loaf,true,sizeof(loaf));
for(int i=2;i<=n;++i)
{
scanf("%d %d",&k[i],&c[i]);
loaf[k[i]]=false;
}
for(int i=1;i<=n;++i)
if(loaf[i]) dp[i]=INF;
else dp[i]=0;
for(int i=n;i>=2;--i)
dp[k[i]]+=min(dp[i],c[i]);
printf("%.2f\n",(double)dp[1]);
return 0;
}