トピックリンクします。https://ac.nowcoder.com/acm/contest/1099/I
O(n)が0に2019を成形した後に特別な処理のために、数を決定したときにパーティション点は、パスの数を計算するルートモジュール2019への各点から第1の距離を算出することができる場合。
書式#include <iostreamの> の#include <アルゴリズム> 書式#include <ベクトル> 使用して 名前空間はstdを、 #define MAXN 100005 の#define INF 0x3f3f3f3fの INTのN、K、CNT、根、ANS、MAXX、ヘッド[MAXN]、サイズ[MAXN]、息子[MAXN]、VIS [MAXN]、NUM [MAXN]。 構造体の縁{ INT に、次の、ヴァル。 } E [MAXN]。 ベクトル < int型 > DIS; ボイド追加(INT U、INT V、INT ヴァル) { E [ ++ CNT] .TO = V。 E [CNT] .next = 頭部[U]。 E [CNT] .val= ヴァル; ヘッド[U] = CNT。 } ボイド dfs_size(int型 U、INT FA)// 求各点子树大小 { サイズ[U] = 1 ;息子[U] = 0 ; 以下のために(int型 ; I I = I =ヘッド[U] E [I] .next) { int型、V = E [I] .TO。 もし(V = FA &&!VIS [V]) { dfs_size(V、U)。 サイズ[U] + = サイズ[V]。 息子[U] =のボイド MAX(息子[U]、サイズ[V])。 } } } Dfs_rootに(INT Nは、int型 Uを、INT FA)// 求重心 { 息子[U] = MAX(息子[U]、N- サイズ[U])。 もし(MAXX> 息子[U]) { ルート = U。 MAXX = 息子[U]; } のために(int型 ; I I = I =ヘッド[U] E [I] .next) { int型、V = E [I] .TO。 もし(!!V = FA && VIS [V]) Dfs_rootに(N、V、U); } } 無効 dfs_dis(int型のu、int型FA、INTヴァル)// 距離のルートにすべての点を決定 { ヴァル%= 2019 ; NUM [ヴァル] ++ ; // ; dis.push_back(ヴァル) のために(int型 I =頭[U]を、I; I = E [I] .next) { int型 V = E [I] .TO; IFは!(V FA = && VIS [V]) (V、U、ヴァルdfs_dis + E [I] .val); } } int型 CAL(INT U、INTヴァル)// パスの計算Kより少ない数 { ため(INT 0I =;私は= < 2019 ; iが++ ) NUMを[I] = 0 ; // dis.clear(); dfs_dis(U、0 、ヴァル)。 // ソート(dis.begin()、dis.end()); INTは L = 0、R = dis.size() - 1、RET = 0 。 用(int型 iは= 1 ; iが< 2019 ; iが++)// 二ポインタ { 場合(NUM [I] && NUM [ 2019 -i])RET + = NUM [I] * NUM [ 2019 - ; I] } RET / = 2 。 RET + = NUM [ 0 ] *(NUM [ 0 ] - 1)/ 2 ; リターンRET; } ボイド DFS(INT U) { dfs_size(U、0 ); マックス = INF; Dfs_rootに(サイズ[U]、U 、0 ); ANS + = CAL(根、0); // この場合、パスはルートを通ってパス数を含めずに計算され、このパスは、後数減算 VIS [ルート] =を1。 ; // 選択された標識されたT ROOは、パーティション後の処理を防止する、横断した ため(int型 I =; I I =ヘッド[ルート] [I] .next E) { int型E = V [I] .TO、ヴァル= E [I] .val; IF(!VIS [V]) { ANS - CAL =(V、ヴァル); // サブツリープラスすべての側面DIS(U、V )パスの数を満たすパスの数が減算された後、 DFS(V); // 再帰パーティション } } } int型のmain() { 一方が(scanfの(" %のD "!&N-)= EOF)を { INT U、 V、ヴァル; のための(INT I = 1 ; I <= N; I ++の) ヘッド[I] = VIS [I] = 0 ; CNT = ANS =0 ; 以下のために(int型 i = 1 ; iがn <; iは++ ) { scanf関数を(" %D%D%D "、&U&V、およびヴァル)。 (U、V、ヴァル)を追加します。 (V、U、val)で追加します。 } DFS(1 )。 printf(" %d個の\ n " 、ANS)。 } 戻り 0 。 }