2019年ナショナルデーオフ牛キャンプ2019ポイントを割り1日目と統治

トピックリンクします。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 
}

 

おすすめ

転載: www.cnblogs.com/chen99/p/11617356.html