分析:這裡要求的是全部節點的距離和,可以定義子問題為:某乙個節點去掉它的某一條邊而形成的子樹中,該節點的距離和以及該子樹的節點數.只需要知道全部節點的該資訊,對每個節點就可以通過其臨界節點的該資訊得到這個節點的距離和.總的時間代價是o(2
∗∣n−
1∣)o(2*|n-1|)
o(2∗∣n
−1∣)
的.相比於o(∣
n∣2)
o(|n|^2)
o(∣n∣2
)的複雜度是有優化的.
**:
class
solution
; sub_tree_info st_infos =;}
;public
: vector<
int>
sumofdistancesintree
(int n, vector
int>>
&edges)
}return result;
}/**
* 生成整個節點陣列
* @param num: 節點個數
* @param e:邊表
*/public
:void
generate_nodes
(int num, edge &e)
}/**
* 計算某個節點切掉它的一條邊,而形成的子樹的資訊(子樹代價和,子樹節點數)
* @param sub_tree_root:該節點的代號(這個節點作為子樹的根節點)
* @param node_cutted:形成子樹的過程中需要切割的節點
* @return 乙個info型別,info::first是子樹代價和,info::second是子樹節點數
*/public
: info calculate_sub_tree
(int sub_tree_root,
int node_cutted)
// 記錄中存在該子樹記錄:
sub_tree_info::iterator it = rnode.st_infos.
find
(node_cutted);if
(it != rnode.st_infos.
end())
// 記錄中不存在該子樹的記錄:
int st_cost =0;
int st_count =1;
for(
int i =
0; i < rnode.edge_number; i++)}
// 記錄得到後將其儲存:(寫了一堆std::move,有必要嗎? 能更簡潔嗎?)
rnode.st_infos.
insert
( std::
move
( pair<
int, info>
( node_cutted,
std::
move
(info
(st_cost, st_count)))
));// 返回記錄:
return std::
move
(info
(st_cost, st_count));
}private
: vector
*nodes;
};
C Garland (樹形DP 子樹計數問題)
又攻克一道樹形dp題,首先子樹計數問題,感覺都是先自下而上跑一遍dfs,然後根據題意然後抉擇得套路。一顆有根樹,分成三棵子樹,保證點權和相互相等。分析 子樹滿足ans 3,並且ans 3 0加入就可以了,滿足兩個點或者以上,就是行 為啥說2以上 這裡就是我得wa得點,可以所有得點值為0,你就知道了 ...
序列計數(記憶化搜尋)(C )
問題描述 小明想知道,滿足以下條件的正整數序列的數量 第一項為 n 第二項不超過 n 從第三項開始,每一項小於前兩項的差的絕對值。請計算,對於給定的 n,有多少種滿足條件的序列。輸入格式 輸入一行包含乙個整數 n。輸出格式 輸出乙個整數,表示答案。答案可能很大,請輸出答案除以10000的餘數。樣例輸...
硬幣問題 記憶化搜尋與遞推的轉換
一 問題描述 有n種硬幣,面值分別為v1,v2,v3,vn,每種都有無限多。給定非負整數s,可以選用多少硬幣,使得面值之和恰好為s?輸出硬幣數目的最小值和最大值。1 n 100,0 s 10000,1 vi s.二 解題思路 將每種面值看作乙個點,表示 還需湊足的面值 則初始狀態為s,目標狀態為0。...