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;
}