1472. Martian Army

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;

}

 

你可能感兴趣的:(ARM)