hdoj6446(木DP)

トピックリンクします。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(10 )。
        以下のためにint型 i = 1 ; iがn <; ++ I)
            ANS = ANS * I%MOD。
        ANS = ANS * 2MOD。
        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(10 ); 
        fenzhi(根、N)。
        以下のためにint型 i = 1 ; iがn <; ++ I)
            ANS = ANS * I%MOD。
        ANS = ANS * 2MOD。
        printf(" %LLDする\ n " 、ANS)。
    } 
    戻り 0 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/FrankChen831X/p/11420582.html