清北NOIPのトレーニングキャンプノート - グラフ理論(グループエリートクラスを増やします)
この記事はからである清北の学校内部のグラフ理論のパン甲斐ファンが執筆ノート、クリアな北から柳鉄が特にあなたに共有するために、非常に詳細でエリートグループクラス、ノートを改善するための訓練キャンプに参加していました!リソースを学ぶの詳細については、マイクロチャネルのサブスクリプション番号noipnoiに焦点を当てます。
最短パス:
1.Floyd アルゴリズム(補間点法):
二点間の最短経路(マルチソース最短)のそれぞれのマップ値行列を取得する重量。
アルゴリズムの説明:
非常に暴力的で古典的なDPは、Jパスに私は2つの状態があるとします。
①i、すぐにはパスjに接続されています:
J②i間接的なリンク、ミドルリンクノード番号k:
DIS [i] [j]はiがjに、各ノードのkが存在し、我々は再びチェックDIS最短経路[I] [K] + DIS [K] [j]を表すと仮定する。
//フロイドのアルゴリズム、時間の複雑さ:O(N ^ 3)
//フロイドのアルゴリズム、時間の複雑さ:O(N ^ 3)
DIS [MAXN] [MAXN] int型。
ため(K = 1; K <= N; ++ K)//列挙を
{
用(i = 1; iが<= N; iは++)
{
(; J <= N; J ++ J = 1)のために
{
12月[I] [j]を=分(DIS [I]、[J]、阻害要因[i]が[K] + 12月[K] [J]); // DP
}
}
}
[清北2019NOIPサマーキャンプのヘルプあなたが彼らの夢のOIを実現するために]
2.Dijkstraのアルゴリズム(無向グラフ、負の右側)。
アルゴリズムの説明:
最短マルチソース!
。最初に、S、すなわち、Sは、= {V}、vが0である、唯一の源を含有します。U、すなわち、付加他の頂点vに含ま:U = {}、残りの頂点を、頂点uおよびvはuはポイントの側に隣接していない場合はV、<U、V>と題する正常値次いで、Uをエッジ場合、 <U、V>∞の重量と。
B. vがKで頂点U kからの最小距離を選択し、Sの添加は、(距離Vは、最短経路長をkに選択されます)。
。Cは、kにUから各頂点を修飾考え新規の中間点であり、元の距離よりも短い(頂点Kなし)(頂点Kを介して)頂点uの距離にソース点V、修飾された頂点のuからのIF距離値、頂点k値プラス修飾右端から距離。
D。すべての頂点がSに含まれるまで、BおよびCの手順を繰り返し
〜上記の混乱ああの概念は理解して、またはあなたの例を与えるにはあまりにも複雑です!次の図!
私たちは、ノード番号1が原点であることを前提としています。
最初のラウンドは、我々は、2,3,4,5,6-番号1に起点ノードからの距離を計算することができるように7,9、∞、∞、14 ]、∞は無限大(ノード間で直接通信していない)、の最小値をとることを表します。図7は、次のノードへの最短経路と先行ノードの最小のものをしながら最短パス1-> 0,1-最短パス1〜7> 2であると判定されます。
第二ラウンド、前駆体の原点+先行ノードへの新しいノードから最短の距離に応じて新たな最小距離を計算するために撮影した先行ノードがノード2で、ノードが起点ノードの数から得られます3,4,5,6- [17,22、∞は、∞](新しいノードがバック正方形に一方のノード番号でなければなりません2)のように、今回の結果と計算、3番ノードの新しいラウンドの結果を比較する必要がある:> 9 17は、最短パスはまだ9;ノード4:22 <∞、数4は、最短経路ノード22で更新し、ノード5:∞は変更されないまま、ノード番号6:14 <∞は、図6は、14ノードへの最短経路を更新します。次の最小ノード3先行ノードのための最短パスしながら最短距離は、ラウンド[9,22、∞、14]、最短経路9に1-> 3が得られます。
第三ラウンド:同じトークンに、前駆体としてのノードにノード3はノード4,5,6を得ることができる原点から1である[20、∞、11]、最短経路、最短距離、および上部の原理に従って次の最小ノード6先行ノードの最短パスしながら比較、[20、∞、11]、最短経路11に1-> 3-> 6をリフレッシュ。
第4ラウンド:同様に、最短距離は4,5ノード与える[20、20]二つの値が等しくない場合、これらの2つの値が等しい、計算の端部は、これら2つのドットから最短距離は、20でありますが、また、第五ラウンド演算のために!
書式#include <cstdioを>
書式#include <CStringの>
const int型N = 100500;
const int型M = 200500;
INTポイント[N] = {0}、{0}、LEN [M] = {0}、CC = 0 = [M] = {0}、次の[M]に。
INT DIS [N]; //最短長、DIS [i]はi番目の点光源(点1)を示し、最短距離であります
これまで[N] BOOL; //現在のノードが最短に決定していません
N INT、M。
Yに対するZのX側の長さ:ボイドAddEdge(int型のx、int型のY、int型Z)//新しいノードとエッジを追加
{
CC ++;
次の[CC] =点[X]。
点[x]は、CCを=。
[CC] = Yであり;
LEN [CC] = Z; Yへ// LEN記録辺の長さX
}
メインint型()
{
int型I、J、K。
scanf関数( "%d個の%のD"、&N、&M)。
用(i = 1; I <= M; iは++)
{
A、B、Cのint;
scanf関数( "%D%D%D"、&、&B、&C)。
AddEdge(A、B、C); //無向グラフ、二回追加します
AddEdge(B、C)。
}
memset(DIS、0x3fを、はsizeof DIS); //最大値を初期化します
DIS [1] = 0; //そのノード番号に1が最短距離0であります
ため(K = 1; K <= N; ++ K)
{
int型MINP、minz = 123456789;
用(i = 1; iが<= N; iは++)
{
もし(!今までに[I])
{
IF(DIS [I] <minz)
{
minz = DIS [i]は、
MINP = I;
}
}
}
これまで[MINP] = 1。
INT今=点[MINP]。
(今)ながら、
{
int型TOX = [今]へ。
場合(DIS [TOX]が> DIS [MINP] + LEN [今])
DIS [TOX] = DIS [MINP] + LEN [今]。
今=次の[今]。
}
}
用(i = 1; iが<= N; iは++)
printf( "%d個の\ n"、DIS [I])。
0を返します。
3.SPFAのアルゴリズム(右側が負、負環が、負出力リングを検出することができない何を持っていません)。
最短マルチソース!
ダイクストラとSPFA非常に類似するが、負リングとエッジの負の重みを検出するために最適化されたキューを追加しました。
アルゴリズムの説明:
次に、キューの確立、キュー場合にのみ、初期開始点、及び全ての点(0割り当てられた自分のパスに最大値が、その点を割り当てるテーブルの初期値)の開始点への最短パスを記録するためにフォームを作成します。リラクゼーション操作は最短リフレッシュのすべての点を出発点として、キューのいくつかと、実行され、リフレッシュポイントがキューへの最終ポイントのキューに置かれていない場合、正常に更新されます。キューが空になるまで繰り返します。
負リングかどうかを決定する:
キューの数が負のN回一定の入力リングを超えている場合(図負SPFAリングを処理していません)
書式#include <cstdioを>
書式#include <CStringの>
const int型N = 100500;
const int型M = 200500;
INTポイント[N] = {0}、{0}、LEN [M] = {0}、CC = 0 = [M] = {0}、次の[M]に。
INT DIS [N]; //最短
int型のキュー[N]、トップ、テール; //双方向キューキュー、HOL、尾
[N]でBOOL; //キューにないの点を記録するが、1で発現し、0ではない示し
N INT、M; // nはノード、M縁
AddEdge(int型のx、int型のY、int型Z)// X辺の長さzはyに無効
{
CC ++;
次の[CC] =点[X]。
点[x]は、CCを=。
[CC] = Yであり;
[A] = Zとして;
}
メインint型()
{
int型I、J。
scanf関数( "%d個の%のD"、&N、&M)。
用(i = 1; I <= M; iは++)
{
A、B、Cのint;
scanf関数( "%D%D%D"、&、&B、&C)。
AddEdge(A、B、C); //以来双方向キューに加え、左右のプラスワン
AddEdge(B、C)。
}
memset(DIS、0x3fを、はsizeof DIS); //最大値を初期化します
DIS [1] = 0; //そのノード番号に1が最短距離0であります
トップ= 0;尾= 1、キュー[1] = 1; [1] = 1; //は起源の、添加のみを初期化します
しばらく(トップ!=尾)
{
トップ++;
トップ%= N。
int型は現在キュー[トップ] =;
[今]に= 0;
int型のED =ポイント[今]。
しばらく(編)
{
int型TOX = [編]へ。
IF(DIS [TOX]> DIS [今] + LEN [ED])
{
DIS [TOX] = DIS [今] + LEN [編];
もし(!で[TOX])
{
尾++;
尾%= N。
キュー[尾] = TOX;
【TOX] = 1。
}
}
ED =次の[ED]。
}
}
用(i = 1; iが<= N; iは++)
printf( "%d個の\ n"、DIS [I])。
0を返します。
}
4.Bellmanフォードアルゴリズム(負右側、負の環を有し、環は、負の出力を検出してもよいです)。
最短シングルソース!
アルゴリズムの説明:
1.初期化:ソース点推定値D [すべて] = +∞、D以外のすべての頂点の最短距離[スタート] = 0;
2.反復解法:操作で繰り返し各側辺集合E緩和、最短距離が徐々に接近頂点の集合Vの各頂点vのための最短距離推定するように、(実行| V | -1回)
各側面が収束する2つのエンドポイント辺集合Eを決定する:3.負サイクルがあることを確認します。[V]のソースからの最短距離は、頂点vまで指すtrue、そうでないアルゴリズム、及びDに格納されている、いない収束頂点が存在する場合、アルゴリズムは、falseを返す問題が解決策を持っていないことを示しています。
簡単に言えば、以下に示すように:
点Bの緩和計算値は8であるが、ポイントの値は重量プラスエッジ2の重量、5を与えるために、点Bの値より前(8)が小さく、従って、点Bの値が5に低減されます。このプロセスの重要性は、B短いルートを指すようにパスを見つけることであり、経路は、2辺の重量その後、点Aを通過することで、点Bに到達します
次のような状況の場合:
[OK]を元の最短経路を保持して、(このアルゴリズムで崇高ベルマンFrod)を変更しないように緩和操作の後、> 6 7,7-なり、コードが実装するのは非常に簡単です。
INTのN、M; // n点、M縁
図中で定義された構造体のエッジ//型構造。
{
A、B、Cのint型; // CにBの長さを
} []エッジ。
INT []と言います。
memset(DIS、0x3fを、はsizeof DIS)。
DIS [1] = 0;
以下のために(INT i = 1; iがn <; iは++)
{
用(J ++ INT J = 1; J <= M)
{
IF(DIS [エッジ[J] .B]> DIS [エッジ[J] .A] +エッジ[J] .C)
{
DIS [エッジ[J] .B] = DIS [エッジ[J] .A] +エッジ[J] .C。
}
}
}
5.Aの*アルゴリズム:
〜私はこのようなものを理解していなかったので、私は(しぶしぶ顔)それのさらに多くの未来を理解します
七、トポロジカル整列:
有向非巡回グラフ(有向非巡回グラフがDAGと称す)Gを位相的にソートするためにエッジ(U、V)の場合、Gのすべての頂点は∈、例えば頂点図UおよびVの任意のペアことが、線形配列に配置されていますE(G)、uはVの前に現れる線状配列。典型的には、そのような配列は、線状配列と呼ばれるトポロジカル順(トポロジカル順)、頭字語トポロジシーケンスを満たします。
アナロジー:私たちは、料理名を作りたいが、ナス、茄子の蒸し煮された後、最初のステップは、食材を買うことだった、第二段階は、ナスを洗う第三段階は、パンああ何七七〇から八に油を注ぐことで開始します8、第四ステップは...あなたが最初にナスや食材を洗う、ナスを購入することはできません、このようなイベントは順番にこれらのイベントの順序に従って実施しなければならないがトポロジカル順序を構成しています。
アルゴリズムの説明:
私達はちょうどだけまでゼロメンテナンスの要素を配置するコンテナを検索するために、両方が無関心することができ、スタックやキューを必要としています。
①選択的に0から(NO前駆体)の頂点の有向グラフに変換し、それを出力します。
②ネットワークから、およびノードから始まるすべての有向辺を削除することによって、ノードを削除します。
残りのネットワークノードがもはやない前駆症状がない存在するまで③上記の2つの手順を繰り返していません。
次のように具体的な動作は以下のとおりです。
スタックが空でない場合= 0度は、その後、スタックにプッシュされた場合、ポップアップスタックの要素とは、その貫通点1(省略片側)の各々の点を列挙することができます。
すべての頂点の出力がない場合、特定の周図が存在します。
//トポロジカルソート、時間計算:O(N + M)
書式#include <cstdioを>
書式#include <CStringの>
const int型N = 100500;
const int型M = 200500;
INTポイント[N] = {0}、[M]へ= {0}、次の[M] = {0}、CC = 0。
INT徐[N] = {0}; //スタックは、最初に空いている、徐[0]は、スタックサイズを示します
[N]のint = {0}; //浸透、[B]において、Bに到達することができる++
INTのANS [N] = {0}; // ANS [0]トポロジーの全体の大きさの
N INT、M。
AddEdge(int型のx、int型のY)// Bに隣接テーブルを無効
{
CC ++;
次の[CC] =点[X]。
点[x]は、CCを=。
[CC] = Yであり;
}
メインint型()
{
int型I、J。
scanf関数( "%d個の%のD"、&N、&M)。
用(i = 1; I <= M; iは++)
{
、B int型。
scanf関数( "%D%dの"、&、&B)。
で[B] ++; //の各ノードごとにカウント
AddEdge(B)
}
用(i = 1; iが<= N; iは++)
{
([I] == 0)//ノードにあれば、スタックにプッシュされ、0であります
徐[++徐[0] = I。
}
一方、(徐[0])
{
intは今徐= [徐を[0]; //出栈
トレンド[0] - 。
年[++年[0] =今;
int型のED =ポイント[今]。
しばらく(編)
{
int型TOX = [編]へ。
で[TOX] - 。
もし(!で[TOX])
徐[++徐[0] = TOX。
ED =次の[ED];次の隣接ノードを見つける//
}
}
(ANS [0] <N)//特定の周図面が存在する場合、結果はありません
printf( "ノーソリューション");
他
{
用(i = 1; iが<= N; iは++)
printf( "%dの"、ANS [I])。
}
0を返します。
}
ユニコムコンポーネント:
強力な通信:AからBへの有向グラフ、及びにBであることができる、次に、bは強固に接続されています。
強いグラフ:有向グラフ、点の任意の対強連結満たすが、これは図の強連結グラフと呼ばれます。
強いユニコムコンポーネント:図中の部分グラフを接続強連結成分に大きな強度があります。
国を強化するための通信コンポーネントとの一般的な使用のためのTarjanのアルゴリズム:
オイラーパスハミルトンパス:
1. オイラー経路:各片側を通してストロークを開始するパスがある点から形成されます。
オイラー:オイラー経路に基づいて経路の先頭へ戻る(出発点からのストロークを各エッジを横断します)。
オイラーパスが存在します。
無向グラフ:図度のすべての頂点が偶数であった二つの外側奇数残りの又はそれに加えてさえ度である場合にのみ。
有向グラフ:場合にのみ、すべてのグラフの頂点または頂点= A + 1-度=侵入、他のアウト度= + 1の頂点、侵入の他の頂点=
オイラーが存在します。
無向グラフ:各頂点の次数が偶数、オイラーあります。
有向グラフ:頂点の各々はオイラーが、次数に等しいです。
オイラーパス/オイラーアルゴリズムは、多くの場合、フルーリアルゴリズムを使用しました。
ここでは、平和の十分な知識をお勧めします:神秘的なOIerを
2. ハミルトン経路:経路はハミルトン経路で正確に一度、各点を通ります。
ハミルトン・サイクル:最初と最後のエッジ間の存在ハミルトン経路は、ハミルトンサイクルに接続されています。