トピックリンクします。https://vjudge.net/problem/HDU-6446
質問が意図される:問題を単純化するために、距離と意図2 *(N-1)倍を計算することです!
アイデア:
DP単純木、及び距離を算出寄与、エッジが(u、v)はSZである[V] *各側の寄与を合計することによって、(N-SZ [V])。
書式#include <cstdioを> する#include <アルゴリズム> 使用して 名前空間はstdを、 typedefの長い 長いLL。 const int型 MAXN = 1E5 + 5 。 const int型 MOD = 1E9 + 7 。 int型N、CNT、ヘッド[MAXN]、SZ [MAXN]。 ANS LL; 構造体ノード{ int型V、NEX。 LLのワット。 }エッジ[MAXN << 1 ]。 ボイド ADDE(INT U、INT V、LLのW){ エッジ[ ++ CNT] .V = V。 エッジ[CNT] .W = W。 エッジ[CNT] .nex = 頭部[U]。 ヘッド[U] = CNT。 } ボイド DFSを(int型 U、int型のFA){ SZ [U] = 1 。 以下のために(int型 ; I I = I =ヘッド[U] {エッジ[I] .nex) のint V = エッジ[I] .V。 もし(== FA V)続けます。 DFS(V、U); SZ [U] + = SZ [V]。 ANS =(ANS +エッジ[I] .W * SZ [V]%MOD *(N-SZ [V])%MOD)%MOD。 } } int型のmain(){ ながら(〜のscanf(" %のD "、&N)){ ANS = 0 。 CNT = 0 ; 以下のために(int型 i = 1 ; iは= N <; ++ I) ヘッド[I] = 0 ; 以下のために(int型 i = 1 ; iがn <; ++ I){ int型、LLのW、V、Uと、 scanf関数(" %D%D%LLD "、&U&V、およびW) ADDE(U、V、W)。 ADDE(V、U、W)。 } DFS(1、0 )。 以下のために(int型 i = 1 ; iがn <; ++ I) ANS = ANS * I%MOD。 ANS = ANS * 2%MOD。 printf(" %LLDする\ n " 、ANS)。 } 戻り 0 。 }
パーティションを学ぶために数日前のでまた、あなたが点線のルールでは、この問題を参照して距離を求めることを期待することができます。実際には、重心距離DISの中心を見つけるために、Uの重心を求めることにより、全ての点[i]は、次にポイントの2番目のパーティションを使用して書かれ、算出された距離の和とのuがvすべてのサブノードをトラバースすることを示し合計は、NUMは、フロント内のノードの数、DIS [i]は、NUMに寄与する* DIS [I] +和の現在の反復を表しています。しかし、エンドポイント側のための重心を漏洩しないように注意してください、それはNUM 1、いない0を初期化します。
点線ルールコード:
書式#include <cstdioを> する#include <アルゴリズム> 使用して 名前空間はstdを、 typedefの長い 長いLL。 const int型 MAXN = 1E5 + 5 。 const int型 MOD = 1E9 + 7 。 const int型 INF = 0x3f3f3f3f 。 int型N、CNT、ヘッド[MAXN]、SZ [MAXN]、MSON [MAXN]、最小、サイズ、根。 int型VIS [MAXN]、トン、NUM; LL DIS [MAXN]、TMP、和、ANS。 構造体ノード{ int型V、NEX。 LLのワット。 }エッジ[MAXN << 1 ]。 無効 ADDE(int型U、int型V、LLのW){ エッジ[ ++ CNT] .V = V。 エッジ[CNT] .W = W。 エッジ[CNT] .nex = 頭部[U]。 ヘッド[U] = CNT。 } ボイド getroot(int型 U、int型のFA){ SZ [U] = 1、MSON [U] = 0 ; 以下のために(int型 ; I I = I =ヘッド[U] {エッジ[I] .nex) のint V = エッジ[I] .V。 もし(VIS [V] || V == FA)続けます。 getroot(V、U); SZ [U] + =SZ [V]。 MSON [U] = MAX(MSON [U]、SZ [V])。 } MSON [U] = MAX(MSON [U]、サイズSZ [U])。 もし(MSON [U] <分)分= MSON [U]、ルート= U。 } ボイド getdis(INT U、INT FA、LL LEN){ DIS [ ++ T] = LEN。 以下のために(int型 ; I I = I =ヘッド[U] {エッジ[I] .nex) のint V = エッジ[I] .V。 もし(VIS [V] || V == FA)続けます。 getdis(V、U、(LEN +エッジ[I] .W)%MOD)。 } } ボイド(解きますINT U){ 和 = 0 。 NUM = 1 。 以下のために(int型 ; I I = I =ヘッド[U] {エッジ[I] .nex) のint V = エッジ[I] .V。 もし(VIS [V])続けます。 T = 0 。 TMP = 0 ; getdis(V、U、エッジ[I] .W)。 以下のために(int型 I = 1 ; I <= T; ++ I){ ANS =(ANS + NUM * DIS [I]%のMOD +和)%MOD。 TMP =(TMP + DIS [i])と% MOD。 } 和 =(和+ TMP)%MOD。 NUM + = T。 } } ボイド fenzhi(INT U、INT ssize){ VIS [U] = 1 。 (U)を解きます。 以下のために(int型 ; I I = I =ヘッド[U] {エッジ[I] .nex) のint V = エッジ[I] .V。 もし(VIS [V])続けます。 分 = INF、ルート= 0 。 サイズ = SZ [V] <SZ [U] SZ [V] :( ssize-?SZ [U])。 getroot(V、0 ); fenzhi(根、サイズ) } } int型のmain(){ ながら(〜のscanf(" %d個"、&N)){ CNT = 0 。 ANS = 0 ; 以下のために(int型 i = 1 ; iは= N <; ++ I) ヘッド[I] = VIS [I] = 0 ; 以下のために(int型 i = 1 ; iがn <; ++ I){ int型、LLのW、V、Uと、 scanf関数(" %D%D%LLD "、&U&V、およびW) ADDE(U、V、W)。 ADDE(V、U、W)。 } 最小 = INF、ルート= 0、サイズ= N。 getroot(1、0 ); fenzhi(根、N)。 以下のために(int型 i = 1 ; iがn <; ++ I) ANS = ANS * I%MOD。 ANS = ANS * 2%MOD。 printf(" %LLDする\ n " 、ANS)。 } 戻り 0 。 }