旅行木の直径を持つHDU 6686リッカイン

問題の意味:(二つの点を含む)の合計を介して別の点に一点から2点間の規定された距離、2つの互いに素経路の提供タプル(x、y)は、長さX、長さyは、何度もありました(x、y)のタプルを尋ねたのですか?

アイデア:JLSは説明することを指示し:

ベース直径演習。
裁判官が表示されないことができます考えてみましょう。傑に:それが発生した場合、その後、直径の両端で使用されているスキームがなければならない、木の直径のいずれかを取ります。エンドポイントが使用されていないが存在すると仮定される、木の直径は長いパスであるので、この移動がなければならないので、一方のエンドポイントが、この直径の上端に移動できるようになり、2つの直線4つのエンドポイントを考慮してください非常に簡単であることが判明しましたこれは、パスの長さを減らすことはありません。
満たすことができる長の要件を満たすために、すべての値以下となるように、それぞれの長さのために考慮する。これらの値は直径を考慮して計算される:最初のケースの端部の直径が異なる経路に属する大きい経路長になるように、その後、エンドポイントは、直径の点で直径そのパスを列挙することができポイントに対するエンドポイントの直径と、この距離に加え、他の経路の大きな長さの外径に延びる長さは、同様に大きい拡張長はDFSの一つによって計算することができ、要求することができます。第二の場合、この直径へのパスが存在することであり、次いで、他のパスが、これは単に削除される直径上の点を配置し、再びラインの直径を求め、長いパスは、この直径を越えて長さです。
合計時間の複雑さはO(N)です。

コード:

 

#include <ビット/ STDC ++ Hが> 
の#define LL長い長い
名前空間stdを使用。
const int型MAXN = 100010; 
ベクター<INT> G [MAXN]。
INTのMPが[MAXN]は、[MAXN]、F [MAXN] mx_dis、のMx [MAXN]。
BOOL V [MAXN]、V1 [MAXN]。
int型の根、MX、今。
ベクトル<整数>; 
ボイド追加(int型のx、int型のY){ 
    G [X] .push_back(Y)。
    G [Y] .push_back(X)。
} 
ボイドDFS {(int型のx、int型FAは、DIS、ブールフラグINT)
    [X] = FA F; 
    V1 [X] =フラグ。
    IF(DIS> MX){ 
        MX = DIS。
        今= xと; 
    } 
    (自動Y:G [X])が{ 
        IF(Y == FA || V [Y])続けます。
        DFS(Y、X、DIS + 1、フラグ)。
    } 
}
INT DFS1(int型のx、int型FA){ 
    int型MX = 0。
    以下のための(自動Y:Gは、[X]){ 
        IF(V [Y] || Y == FA)続けます。
        MX = MAX(MX、DFS1(Y、X)); 
    } 
    MX + 1を返します。
} 
int型のmain(){ 
    int型T、X、Y、N。
// freopenは( "6686in.txt"、 "R"、STDIN)。
// freopenは( "out1.txt"、 "W"、STDOUT)。
    scanf関数( "%のD"、&T)。
    (T--){一方
        のscanf( "%d個"、&N); 
        a.clear(); 
        以下のために(INT i = 1; iが++; iが<= n)を
            G [i]が.clear(); 
        {ため(iは++; iがn <I = 1 INT)
            のscanf( "%d個の%のD"、およびX&Y)。
            (x、y)を加えます。
            V [I] = v1の[I] =融点[I] = F [I] = mx_dis [I] = 0; 
        ルート= 1、MX = 0。
        DFS(ルート、0、1、0); 
        ルート=今、MX = 0; 
        DFS(ルート、0、1、0); 
        {(; I I = [I] fを今= INT)のため
            のV [I] = 1。
            a.push_back(I); 
        } 
        のための(自動X:A){ 
            mx_dis [X] = DFS1(X、0); 
        } 
        ため(; iがn = <; I = 1 int型私は++)V1を[I] = 0; 
        int型のTMP = 0; 
        以下のために(; iがn = <; iは1 = int型私は++){ 
            IF(V [I] == 0 && V1 [i]が== 0){ 
                今= MX = 0。
                DFS(I、0、1、0);
                DFS(現在は、0、1、1)。
                TMP = MAX(TMP、MX)。
            } 
        } 
        MP [a.sizeは()] TMPを=。
        [TMP] = a.size融点()。
        MX [a.size()] = 0; 
        以下のために(私は= a.sizeをINT() - 2; I> = 0; i--){ 
        	のMx [I + 1] =最大(MX [I + 2]、(INT)a.size() - 、I - 2 + mx_dis [[I + 1])。
		} 
        ため(;私は()a.sizeを< - 1; iは0 int型私は++){ 
            int型のx = I + mx_disを[I]]。
            Y = INTのMx [I + 1]。
            MP [X] = MAX(MP [X]、Y); 
            MP [Y] = MAX(MP [Y]、X)。
        } 
        LL ANS = 0。
        MX = 0; 
        以下のために(()I = a.size int型; I> = 1; i--){
            MX = MAX(MX、MP [I])。
            ANS + = MX。
        }  
        のprintf( "%LLDする\ n"、ANS)。
    }        
}

  

おすすめ

転載: www.cnblogs.com/pkgunboat/p/11407720.html