トピックリンク:
CF:http://codeforces.com/contest/161/problem/D
Luogu:https://www.luogu.org/problem/CF161D
点線のルール裸のタイトル。
重要な点は、分割して答えを更新征服する方法です。
そして、ルートパーティションを見つけるための手順は簡単です。
この質問は、まさに数K.のツリーパスが必要です
それはかもしれKに等しいパスの数よりも小さいマイナスのパスの数は、K未満であります
他のは非常に日常的です。
コードは以下の通りであります:
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 const int型 MAXN = 50010 ; 構造体ノード{ int型NXT、DIS、であり; #define NXT(X)E [X] .nxt の#define(X)E [X] .TOへ の#define DIS(x)は、E [x]は.DIS } E [MAXN << 1 ]。 int型のヘッド[MAXN]、TOT、N、K。 インラインボイド追加(INT から、INTに、int型の{DIS) (へ ++のTOT)=に、DIS(TOT)= DIS。 NXT(TOT) =ヘッド〔から]; [ヘッドからは ] = TOTを、 } int値をmaxP [MAXN]、[MAXN] SIZ、VIS [MAXN]、合計、RT。 インラインボイド getrt(int型今、INT FA){ SIZ [今] = 1 ;をmaxP [今] = 0 ; 以下のために(int型 I =; I I =ヘッド[今] {NXT(I)) INT =への(I) 場合(VIS || [する] FAを==する)続けます。 getrt(今に); SIZ [今] + = SIZ [します]。 maxP [今] = MAX(をmaxP [今]、[する] SIZ)。 } maxP [今] = MAX(をmaxP [今]、sum- SIZ [今])。 もし RT =(<をmaxP [RT] [今]をmaxP)今。 } INT 再[MAXN]、DEP [MAXN]、CNT。 長い 長い ANS = 0 ; インラインボイド getdisは(int型今、INT FA){ 再[ ++ CNT] = DEP [今]。 以下のために(int型 I =; I I =ヘッド[今] {NXT(I)) INT =への(I) 場合(==にFA || VIS [に対して])続けます。 【に】DEP = DEP [今] + DIS(I)。 (今に)getdis。 } } インラインINT CALC(INT今、INT W){ CNT = 0 ; [今] DEP = W。 getdis(今、0 ); ソート(RE + 1、再+ 1本の + CNT)。 int型、L = 1、R = CNT、RES = 0 。 一方、(L < R){ 場合(RE [L] +再[R] <= K)RES + =(RL)、L ++ 。 他の r--の; } 、L = 1、R = CNT。 一方、(L < R){ もし(再[L] +再[R] <K)RES - =(RL)、L ++ 。 他の r--の; } 戻りRESと、 } インラインボイドは(解決INTを今){ ANS + = CALCを(現在は、0 VIS [今] =;)1 。 以下のために(int型 I =; I I =ヘッド[今] {NXT(I)) INT =への(I) もし(VIS [する])続けます。 ANS - = CALC()I(DIS、へ)。 RT = 0 ;和= SIZ [します]。 getrt(へ、0);); (RT)を解きます。 } } int型のmain() { scanf関数(" %D%dの"、&N&K)。 以下のために(int型 i = 1 ; iがn <; iは++ ){ int型Uを、V。 scanf関数(" %d個の%d個"、&U&V); (uは、vは、追加1)、追加(V、U、1 )。 } 和 =をmaxP [ 0 ] = N。 RT = 0 ; getrt(1、0 (RT)を解きます。 printf(" %I64dの\ n " 、ANS)。 システム(「一時停止」)。 リターン 0 ; }