テーマ別9つの連結グラフE POJ 3177冗長パスを[Kuangbinは飛ぶためにあなたを取ります]

私はこの質問を始め、二重連結成分の直接のポイント収縮であると考え、これらの二つの成分ユニコムはまだラインではなく、接続?

しかし、私たちのいずれかのこれらの二つの成分ユニコム間のエッジ接続すれば、ダブルダブルユニコム内部通信、正しくない、それらの間にブリッジが本当に知りませんありません。

私はそれが祭り自体のために、それを接続する唯一の橋がある葉ので、我々は2つのリーフノードを接続することができ、リーフノードの数を縮小した後の点を求めているべきです。次に、2つの領域は、二つの成分ユニコム領域を合成します。一方、使用側を削減するために、我々は2つの点がリーフノードで接続することができます。最後に1、残りは接続する必要があります。これは二重通信に算出し、図に非常に簡単にでき、エッジの数が必要。

書式#include <iostreamの> 
書式#include < 文字列の.h> 
の#include <アルゴリズム> 
書式#include <stdio.hに>
 使って 名前空間はstd;
CONSTの INT N = 1E4 + 5、M = 1E5 + 5 int型のヘッド[N]、次に[M]、[M]版、低い[M]、DFN [M]、スタック[M]。
int型のブロック;
INTは、[M]、度[M]属します。
BOOL brige [M]、イン[M]。
INT [M]、DCC、トップC。
INTのTOT、N、M、NUM、CNT。
ボイド追加(int型のx、int型のY)
{ 
    版[ ++ TOT = Y。
    次【TOT] = 頭部[X]。
    ヘッド[X] = TOT。
} 
ボイド tarjan(INT U、INT PRE)
{ 
    int型V、
    DFN [U] =低[U] = ++ NUM。
    スタック[ ++トップ] = U。
    イン[U] = 1 int型 ; I I = [U] I =ヘッドを次に[I])
    { 
         V = 版[I];
        もし(V ==前)続けますもし(!DFN [V])
        { 
            tarjan(V、U)。 
            低い[U] =分(低[U]、低[V]);
             IF(低[V]> DFN [U])
            { 
                brige [I] = 1 ; // マークブリッジ 
                brige [I ^ 1 ] = 1 ; 
                CNT ++ ; 
            } 
        } 
        そうでなければ低[U] = 分(低[U]、DFN [V]); 
    } 
    IF(低[U] == DFN [U]){ // 現在のノードがルートである場合、私たちDFSは、この後にコンポーネントを接続 
        CNT ++ ;
         DO 
        { 
            V =スタック[top--]; // 連結成分の全ての点への裏返しであります
            イン[V] = 0 ; 
            C [V] = CNT。// 标记上所在的连通分量 
        } しばらく(U =!V); 
    } 
} 
ボイドのinit(){ 
   memsetの(次に、0はsizeof (NEXT))。
   memsetの(低い、0はsizeof (低))。
   memset(brige、0はsizeof (brige))。
   memsetの(頭、0はsizeof (ヘッド))。
   memset(版、0はsizeof (版))。
   memsetの(DFN、0はsizeof(DFN))。
   memset(C、0はsizeof (c)参照)。
   TOT = 1 
   CNT = 0 ; 
   NUM = 0 ; 
   DCC = 0 ; 
   トップ = 0 ; 
} 
int型のmain()
{ 
    int型Uを、V。
    一方、(〜のscanf(" %d個の%のD "、&​​N、&M))
    { 
        INIT()。
        以下のためにint型 I = 1 ; I <= M; iは++ 
        { 
            (scanf関数"%d個の%d個"、&​​U&V); 
            (V、U)を追加します。
            (V、U)を追加。
        } 
        のためにint型 i = 1 ; iが<= N; iが++ ){
             場合(!DFN [I]){ 
                tarjan(I、I)。
            } 
        } 
        のためにint型 i = 1 ; iがn = <; iは++ ){
             ためint型 J =ヘッド[I]; J; J = 次に[J])
            { 
                  場合(brige [J])    // 缩点后把桥两边的缩点的度++ 
                    度[I] [C] ++ ; 
            } 
        } 
        のInt ANS = 0 ;
         のためのint型 I = 1 ; Iは= CNTを<; Iは++ ){
             IF(DEG [I] == 1){ // 我々は、点1の集点を見つけ、すなわち、葉ノード、 
                ANS ++ ; 
            } 
        } 
        のprintf(" %Dの\のN- "、(+ ANS 1)/ 2); // (ポイントを凝縮した後+1リーフノード番号)コネクタ部品ユニコムの所望の二重側面図= / 2
         //はそれは私が2アップで接続された2つのリーフノードを入れてシンプルなので、この辺は少なくとも消費されます。私たちは、描画を行うことができるように、
         //は、二重ユニコムに変身
     }
     の戻り 0 ;
}

 

おすすめ

転載: www.cnblogs.com/bluefly-hrbust/p/11229408.html