P5021の軌道建設
分析:
それは半分の値には明らかです。
トラックと点との間の関係のためにuが3つのケースに分けることができます。
完全サブツリーU内の1。半分2.サブツリー、U後サブツリー3の外側の半分は、他方の鎖は、サブツリーに接続されています。
最初のケースで、直接、彼が貢献を含め再帰インチ
第2の3のケースでは、多重集合を開いて、発生した法的な値はマルチセットに配置されます。
バックたびに、最初のサブツリーができ二十から二を組み合わせマージされず二十から二合わせ、最大かかる親ノードと一致するように左。
マルチセットの詳細がたくさんあります:
1.消去がどちらかの値を削除することができ、あなたはまた、場所を削除することができます!!
2.クラッシュで、その結果、この時間を空にするポイント、ポイントにポイントした後、削除しないで、重要であり、その点順を削除します。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 #defineは、 INTレジスタRI の#define N 50005 int型のヘッド[N]、NEX [N << 1 ]乃至[N << 1 ]、TOT = 0、W [N << 1 ]、N、M、中間、ANSを; ボイド追加(int型、INT B、int型 WW)を{TOT ++。【TOT = Bへ; NEX [TOT =ヘッド[A]。ヘッド[] = TOT。【TOT] W = WW。} 多重集合 < INT > ST [N]。 マルチセット < 整数 > ::イテレータそれ。// !!!在外面定义才能遍历完 int型 DFS(int型のu、INT FF) { ST [U] .clear(); int型のval; 用(; iは= RI I =ヘッド[U] {NEX [i])と のint V = に[I]を、 もし(V == FF)は継続。 ヴァル = DFS(V、U)+ [I] W。 もし(ヴァル> = MID)ANS ++; // 子树内的链直接满足情况、就ANS ++ 他のST [U] .insert(val)で、 } INT MX = 0 。 一方、(!ST [U] .empty()){ 場合(ST [U] .size()== 1)リターン MX = MAX(MX、* ST [U] .begin())。 それST = [U] .lower_bound(ミッドST * [U] .begin()); // 対応する位置を見つける IF(ST [U] .begin()&& == IT ST [U] .count(ITを* )== 1)それが++; // 見つかった場合、それ自体がスキップ // 値がない場合ではないが存在し、対応するこの値を削除するために、それが小さすぎること、それと対をなす IF(STイット== [U]。エンド())=最大MX(MX、ST * [U] .begin())、ST [U] .erase(ST * [U] .begin()); // なお、削除の価値!! 他 { // そうでない場合は、対応する位置と対にされる ANS ++ ; // 注配列:それを削除し、削除後に爆発する、それは開始を指している場合、それは空をポイントする、開始する最初 .erase ST [U]をを( IT); ST [U] .erase(ST [U] .begin()); // これは削除の先頭位置であり、複数の値があるため、値ではなく、一方のみの位置 } } リターンMX; } int型のmain() { scanf関数(" %D%D "、&N、&M)。 int型の合計= 0 、A、B、WW。 用(RI i = 1 ; I <= N- 1のscanf(; ++ i)が" %D%D%D "、&、&B、&WW)、(A、B、WW)を追加し、(B、Aを追加、WW)、和+ = WW。 INTは L = 0、R =和+ 1、ANSS = 0 。 一方、(L < R){ 半ば =(L + R)>> 1。ANS = 0 ; DFS(1、0); もし(ANS <M)、R = ミッド。 他リットル=ミッド+ 1、ANSS = ミッド; } のprintf(" %D \ n " 、ANSS)。 }