まず、定義
カットポイント無向グラフ接続図、(すなわち、任意の2点間で相互に到達することができない)は、一緒に、図の頂点を削除しない場合、頂点は点または切断されるように:カット点がポイントである場合エッジポイントを削除するために通信される点に関連付けられた図になるだけでなく、。
図切削エッジ/ブリッジは:一つのエッジを削除する場合は、図通信図面への通信は、このエッジは、切断エッジでフリーではありません。又は:エッジは変化が図は、エッジを削除通信しない場合にのみ、切断エッジです。
II。
カットポイント、カットポイントとブリッジを見つけるために、DFS(ディープサーチ)を使用して、ブリッジを探しています。まず、以下の点をクリアする:1を、DFSの図は、対応するDFSツリーをトラバースすることと同じです。
図2に示すように、ルートに関係なく、その時点の無向DFSツリーは、全ての点を介して行うことができます。
図3に示すように、ツリーは無向グラフをDFS、横方向のクロスエッジ(2つのサブツリーを接続するエッジ)は存在しません。
元深さ優先探索のうち、深さ優先探索は、スパニングツリーを生成します。uのための定義されたDFS [U]は深さにトラバースされるUまたは彼のサブツリーのシーケンス番号、低い[U]をまたがる最初の探索は、非親 - 子ノードの第1の側にさかのぼることができます。
①カット頂点ポイント、次の条件のいずれかです。
1)ルートである.U、Uは、2つの以上の分岐を有する/ uが一つのサブツリー以上を有しています。
2).Uは、存在を満たす(u、v)はまた、親子エッジとして知られている側枝(すなわち探索木におけるuおよびvの父である)として、(u、v)は木のエッジと低いがルートではない[V] > = DFN [U]。ロー(U)=分{DFN(U)、(V)、低(u、v)は側枝/親子縁、DFN(V)である場合には(u、v)は後方エッジ/エッジ先祖返りである場合}
②ブリッジ無向エッジ(U、V)、及び場合にのみ、(u、v)は側枝であり、そして場合DFNを満足[U] <低[V]。注意:1、プログラミングを容易にするため、我々は[V] Uを判断するために、低採用しています。(理論的に低い[U]に決定することができるカット点)
第三に、プログラム
低およびDFN二つの配列を準備します。低配列は、タグの配列、ルートノード強連結部分グラフレコード検索は、サブツリー(非常にRaozuiは、ダウン見て、あなたが理解しましょう)ポイントのDFN値です。この点、いくつかの検索の最初のものである点を検索する時間を記録するDFNアレイ。いくつかのルールによると、検索を介して実行します。(バックトラックなし)、スタックの操作、我々は有向グラフの強連結成分を得ることができます。
1.配列の初期化:あなたが最初の点pを検索すると、配列のDFNと低い値は、その時点までです。
2.スタック:ポイントに各検索、それはスタックの最上部に押し込まれます。3「(時間DFN [P]が場合)P場合は、この時点で、接合」スタック(父と息子側)上の点P、Pの分(低(P)の低い値は、DFN(点Pが存在しますP「))。
P「の場合(時間DFN [P]は場合)、この時点で、接合された」4点pと点pが(エッジの後)スタックしていない場合に、P分(低(P)の低い値は、低(P「))。
5.上記の操作(すなわちサブツリーすべてトラバースされている)を介して、探索点が等しいDFN低い値であるときはいつでも、それはよく、その要素の上にある、スタックからポップ。スタックのこれらの要素強連結成分。
6.すべての点がトラバースされるまで、(全体は、有向グラフ切断二つの部分に分割可能であるため、おそらく、検索の開始点を置換)検索を続けます。
のみ各頂点に一度アクセスするので、各エッジは、我々は、図の強連結成分を有することがOで(N + M)の時間を決定することができ、一度だけ訪問しました。
第四に関わらずどのサイトのあるように見える、アプリケーション1、図で示される通信網の通信の高度、より信頼性の高いシステム
外部の被害を受けたか、障害、システムの正常な動作には影響しません。2、重い航空ネットワーク接続の場合、ルートは天候などの何らかの理由で閉じているときに、訪問者がまだ他のルートからの迂回を取ることができます。
大規模集積回路のクリティカルパスは、その後、いくつかの構成要素の故障の場合には、膜全体の機能は敵を破壊し、戦争で、逆に、輸送ラインに影響を与えていない、再通信するように設計されている3、 、そのトランスポートネットワークにおける関節点のちょうど破壊をすることができます。カットポイントテンプレート:
#include <cstdioを> する#include <CStringの> する#include <cstdlib> の#include <cmath> の#include <アルゴリズム> の#include <ctimeの> 使用して 名前空間STD。 const int型 N = 1000005 ; int型のT、CNT、ヘッド[N]、息子[N]、DFN [N]、低[N]、N、ANS、M、ルート。 BOOL is_ok [N]。 構造体ノード{ int型、U、V、次; }エッジ[N]。 空プッシュ(int型のu、int型V){ ++ cntを。 エッジ[CNT] .U = U。 エッジ[CNT] .V =V; エッジ[CNT] .next = 頭部[U]。 ヘッド[U] = CNT。 } ボイド tarjan(int型 V、int型U)を{ 低い[V] =のDFN [V] = ++ T。 以下のために(int型 - ;!I = I =ヘッド[V] 1 ; I = {エッジを[I] .next) ++ 息子[V]。 INT V1 = エッジ[I] .V。 もし(DFN [V1] == - 1 ){ tarjan(V1、V)。 低[V] = 分(低[V]、低[V1])。 もし(V ==ルート&&息子[V]> = 2 ){ is_ok [V] = 真。 } 他の 場合(V =ルート&&低[V1]> =!{DFN [V]) is_okは[V] = 真。 } } そう であれば(V1 =!U){ 低い[V] = 分(低[V]、[V1] DFN)。 } } } int型のmain(){ memsetの(頭、 - 1、はsizeof (ヘッド))。 memset(DFN、 - 1、はsizeof (DFN))。 memsetの(is_ok、偽、sizeof (is_ok))。 int型のuを、V。 scanf関数(" %d個の%のD "、&N、&M)。 以下のために(int型 I = 1 ; I <= M; iは++ ){ scanf関数(" %d個の%のD "、&U、およびV)。 プッシュ(U、V); プッシュ(V、U); } ルート = U。 tarjan(U、0 ); 以下のために(int型 i = 1 ; iが= <N; iは++ ){ 場合(is_ok [I]){ ++ ANS。 } } printf(" %d個の\ n " 、ANS)。 以下のために(int型 i = 1 ; iは= N <; iは++ ){ 場合(is_ok [I]){ のprintf(" %dの" 、I)。 } } 戻り 0 。 }