http://acm.timus.ru/problem.aspx?space=1&num=1472ios
題目大意:測試
一顆樹,根節點(1) 的值爲 1.0,全部葉子節點的值爲 0.0 ,其餘節點值任意spa
最後要求的是 全部相鄰兩個節點的值差的總和最小。blog
思路:遞歸
假設一個葉子節點爲 c ,他的父節點爲 b ,b的父節點爲 a,那麼 c 的值爲 0.0,get
此子樹的最優結果爲 (value[a]-value[b])*cost[a->b] + (value[b]-value[c])*cost[b->c] 的最小值string
由於value[c]=0.0 肯定,那麼value[b]的值要麼爲 0.0 要麼爲value[a] 這要取決於 cost[a->b] 和 cost[b->c]io
的大小關係,value[] 差值爲0的那一段能夠去掉,而後若是a還有其餘枝葉,要累加。class
而後以這種思想逐步向上遞歸,直到根節點。看代碼能夠一目瞭然。stream
剛開始一直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; }