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