[Bzoj2878] [Noi2012]ロスト遊園地(ツリーリングDP)

bzoj luogu

質問の意味:ナンバーワンツリーまたはリングは、特定のポイントからランダムスタートを取ってきた、それはポイントをオフに行く必要はありませんが、希望の長期的なパスを求める方法はありません。

木の場合:

2が上方この時点から記録した降りるとDP $ $配列が望ましいです

言って$ DP $言うまでもなくを下ります

上がる$ DP $:

DPからV $ U $ $ $の計算のために

$ Dpを[V]は、すべてのパスが、その後のT $のdeg_ {U} -1 $で割った所望の経路にUから減算され周囲に描画されるべき$

リングのツリーの場合:

リング上の非常にいくつかのポイント。

この時点DPで$ $上方たい2つのUからの薬指のリングにスタートを歩いて上。

計算方法:各点について二つのリングリングDPたびに平均化されています。

完成しました。

書式#include <cstdioを> 
する#include <アルゴリズム>
 使用して 名前空間はstdを、
const  int型 N = 100011 ;
constの ダブル EPS = 1E- 8 ; 
テンプレート <型名TP> ボイドリード(TP&KK){
     の#define AKの*の
    TPのPHY = 0、IOI = 1チャー CH = GETCHAR()。
    一方、(CH < ' 0 ' || CH> ' 9 '){ 場合(CH == ' - ')IOI = -1 ; CH = GETCHAR();}
     一方(CH> = ' 0 ' && CH <= ' 9 '){PHY = PHY * 10 + CH- ' 0 ' ; CH = GETCHAR();} 
    KK = PHYのAKのIOI。
} 
int型、N Mと、
構造体sumireko 
{ 
    int型、にNE、W。
} E [N * 2 ]。
int型彼[N]、ECNT。
ボイド addline(int型の F、int型の T、INT W)
{ 
    E [ ++ ECNT] .TO = T。
    E [ECNT] .NE = 彼[F]。
    彼[F] = ECNTを。
    E [ECNT] .W = W。
} 
BOOL ONR [N]。
度[N]、皮下[N]、DPU [N]、DPD [N]。
ボイド DFS1(int型のx、int型F)
{ 
    ためint型 ; I I = I =彼[X]、T E [I] .NE)
    { 
        T = E [I] .TO。
        もし(T == F || ONR [T])続けます
        DFS1(T、X)。
        DPD [X] + = DPD [T] + E [I] .W。
    } 
    もし(SC [X]> EPS)DPD [X] / = SC [X]。
}
ボイド DFS2(int型のx、int型F)
{ 
    ためint型 ; I I = I =彼[X]、T E [I] .NE)
    { 
        T = E [I] .TO。
        もし(F == T || ONR [T])続けます
        DPU [T] = E [I] .W。
        もし(DEG [X] - 1.0 > EPS)DPU [T] + =(DPD [X] * SC [X] -e [I] .W-DPD [T] + DPU [X] *(度[X] -sc [X]))/(度[X] - 1.0 )。
        DFS2(T、X)。
    } 
} 
int型RND [N]、HP。
int型の SP; ブールVV [N]。
int型のfind(int型X、int型F)
{ 
    場合(VV [X]){SP = xで。戻り 1 ;} 
    VV [X] = 1int型TMP;
    int型 ; I; I =彼[X]、T I = E [i]は.NE)
    { 
        T = E [I] .TO。
        もし(T Fを==)続けますもし(TMP = 検索(T、X))
        { 
            場合(TMP == 1 
            { 
                RND [ ++ HP] =のX。
                ONR [X] = 1 もし(!X = SP)の復帰 1 
            } 
            戻り 2 
        } 
    } 
    戻り 0 
} 
二重DPT [N]。
ボイド DFS3(int型のx、int型の F、INT O、INT S)
{ 
    場合(!O)
    { 
        int型 G = 0 int型 ; I; I =彼[X]、T I = E [i]は.NE)
        { 
            T = E [I] .TO。
            もし(!ONR [T])続け; 
            G ++ ; DFS3(T、X、G、S)。
            DPU [X] + = DPT [T] + E [I] .W。
        } 
        DPU [X] / = 2 返します
    } 
    二重 TMP = 0 
    DPT [X] = 0 int型 ; I; I =彼[X]、T I = E [i]は.NE)
    { 
        T = E [I] .TO。
        もし(!ONR [T] || T == S || T == f)を続けます
        DFS3(T、X、O、S)。
        DPT [X] + = DPT [T] + E [I] .W。
        TMP + = 1 ; 
    } 
    もし(SC [X] + TMP> EPS)
    DPT [X] =(DPT [X] + DPD [X] * SC [X])/(SC [X] + TMP)。
} 

二重ANS。
int型XI、YI、WI;
INT メイン()
{ 
    (n)を読み取り、読み取ら(M)。
    以下のためにint型 i = 1 ; iが<= M; iは++ 
    { 
        (WI)読み取り、(YI)を読み出し、(XI)を読み取ります。
        addline(XI、YI、WI)、addline(YI、XI、WI)、DEG [XI] + = 1、DEG [イル] + = 1 ; 
    } 
    もし(m個の== N- 1 
    { 
        INT I = 1; [i]は[I] = deg)とI ++は皮下- 、iが<= N 1 
        SC [ 1 ] + = 1 ; 
        DFS1(10 ); 
        DFS2(10 );
        以下のためにint型 i = 1 ; iが<= N; iは++)ANS + =(DPDを[I] * SC [I] + DPU [I])/ 度[I]。
        ANS / = N。
        printf(" %.5lfする\ n " 、ANS)。
        リターン 0 ; 
    } 
    を見つける(10 );
    以下のためのint型 I = 1?iが<= N; iが++)SC [I] =゜[I] - ([I] ONR 2.01.0 )。
    以下のためにint型 I = 1(RND [i]は、DFS1 iは++; I <= HP)0 );
    以下のためにint型 I = 1 ; I <=馬力; iは++)DFS3(RND [i]は、00 、RND [I])。
    以下のためにint型 I = 1(RND [i]は、DFS2 iは++; I <= HP)0 );
    以下のためにint型 i = 1 ; iが<= N; iは++)ANS + =(DPDを[I] * SC [I] + DPU [I] *(DEG [I] -sc [I]))/ 度[I]。
    ANS / = N。
    printf(" %.5lfする\ n" 、ANS);
     戻り 0 ; 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/rikurika/p/11271194.html