学習アルゴリズム:分割統治ポイント

定義

すべてのサイズの木[重心]は、ツリー全体のポイントの半分以下のサイズをサブツリー

この時点で最大サブツリーは確かに最も時間の焦点である各点の重心を見つけるために[ストライク]、

 

 


 

[問題]

図処理距離

このように:

n個の点、シーク距離がk点の数のマップと同じです

図nは素数の点の数に等しい距離内の点

点kに等しい距離が存在するか否かを画像内のn個の点、

......................................

 


 

[ソリューション]

 直接マング、N ^ 3の複雑さ、確かに炒め

だから我々は大幅にその複雑さを軽減する方法を考える必要があるので、彼は使用分割統治を

ツリーにそれを作るために、このDAGのルートとしてノードを選択し、

それはその後、ここで、木になった一方、ディ劉Doulouに根を想像することは、サブツリーのいくつかの作品です

 

だから、状況の要件を満たすために距離が、2があり、

最初の2つの点が同じサブツリーにあります

第二:二つの異なるサブツリー内のポイントが、彼らが、ルートノードとなっていることは明らかです

 

だから我々は計算距離のルートに様々なポイントを、その後、いくつかの並べ替えを比較nlogn時間内に答えを求めることができるようになり、私たちは、第二の例の問題を解決することができます

 

最初のケースでは、我々は、彼らが2つの異なるサブツリーになり、樹木の根が操作可能になる見つけるために下に進みます

この方法では、最初のケースは、第二になり、我々は唯一の第二に対処する方法を検討する必要があるでしょうし、第一、第二になる方法

 

最初は、チェーンは、O(N)プロセス、決定的GG可能性がないことを選択した場合、ルートが選択され、ルートに第2のキーを選択することです

できるだけ小さな層を分割し、征服する方法の少ない層の場合、効果の半分に到達するために2つの側面をバランスしようLOGNに減少させることができるので、我々は重心を取る必要があります、

ルートは、重力の中心であるので、以下のサブツリーの層の数は最小になり

 

 

 

#include <地図> 
の#include <cstdioを> 
する#include <iostreamの> 
する#include <アルゴリズム>
 使用して 名前空間STDを、
const  int型 MAXN = 10010 ;
const  int型 MAXM = 20010 ;
const  int型 MAXK = 10000010 ;
構造体ノード
{ 
    int型に、
    int型のval;
    int型のnt; 
}エッジ[MAXM]。
int型   ST [MAXN]は、[尋ねる110を、トップ];
INT   SIZ [MAXN]、[MAXN]、ルートF。
int型  DIS [MAXN]、[MAXN]、S、CNT、N、M。
int型  ANS [MAXK]。
BOOL VIS [MAXN]。
ボイド追加(int型のx、int型の Y、int型Z)
{ 
    トップ ++。エッジ[トップ] = {Y、Z、ST [X]}。ST [X] = 頂。
} 
ボイド get_root(int型のx、int型FA)
{ 
    SIZ [X] = 1、F [X] = 0 ;
    以下のためにint型 ; I I = I = ST [X] エッジ[I] .nt)
    { 
        int型へ= エッジ[I] .TO。
        場合(==するFA || VIS [します])続け; 
        (X、へ)get_root。
        F [X] = MAX([x]は、SIZ F [します])。
        SIZ [X] + = SIZ [します]。
    } 
    F [X] = MAX(F [x]は、S - SIZ [X])。
    もし([X] <F F [ルート])
    { 
        ルート =のX。
    } 
} 
ボイド get_dis(int型のx、int型 FA、int型のD)
{ 
    DIS [ ++ CNTは] = [X]を。
    以下のためにint型 ; I I = I = ST [X] エッジ[I] .nt)
    { 
        INT =までをエッジ[I] .TO。
        場合(VIS || [する] FAを==する)続けます
        【へ] = D + エッジ[I] .val。
        get_dis(X、に、[します])。
    } 
} 
ボイドが解決(int型のx、int型 LEN、INT W)
 //
 { 
    CNT = 0 
    [X] = LEN。
    get_dis(X、0 、LEN)。
    以下のためにint型 I = 1 ;私は= CNTを<; I ++ のためのint型 J = 1 ; J <= CNT; J ++
        { 
            もし!(I = J && DIS [I] + DIS [J] < MAXK)
                ANS [DIS [I] + DIS [J] + = W。
        } 
} 
ボイド除算(INT X)
{ 
    (X、解決01 )。
    VIS [X] = 1 以下のためにint型 ; I I = I = ST [X] エッジ[I] .nt)
    { 
        int型へ= エッジ[I] .TO。
        もし(VIS [する])続けます
        解決(エッジに[I] .val、 - 1 )。
        S= SIZ [X]、ルート= 0、F [ 0 ] = N。
        (X、へ)get_root。
        除算(ルート)。
    } 
} 
int型のmain()
{ 
    scanf関数(" %D%dの"、&​​N、&M)。
        以下のためにint型 I = 1 ; I <= N- 1、I ++ 
        { 
            int型X、Y、Z。
            scanf関数(" %D%D%D "、およびX&Y、およびZ)。
            (x、y、z)を加えます。
            (Y、X、Z)を追加します。
        } 
        SIZ [ 0] = 0、F [ 0 ] = N、ルート= 0、S = N。
        get_root(10 ); 
        除算(ルート)。
        以下のためにint型 iは= 1 ; I <= M iは++ 
        { 
            int型のkは、
            scanf関数(" %のD "、&K)。
            もし(ANS [K])
                のprintf(" AYEする\ n " );
            
                のprintf(" NAYの\ nを" ); 
        } 
    リターン 0 ; 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/rentu/p/11284495.html