基本的なコンセプトマップ
図アセンブリは頂点と辺で構成され、G = <V、E>。
Vは、点の集合であります
Eは辺集合であります
有向エッジ、有向グラフ
側に無向グラフ、無し
権利ん、右側にポイント右、負の右
リング、ループバック、複数のエッジ、非循環有向グラフ(DAG)
パスは、パスは単純です:ポイントは、通信を繰り返していません
ツリー:N-1のエッジに接続グラフ、完全グラフのn点:各辺所定の方向に完全グラフ、ツリー環基:エッジ(無向グラフ)、トーナメントを有する任意の2点間:リング、他の完全なツリー、サボテンがある。せいぜい本一つの環において、環が、各側面があってもよいです
入力モードマップ
行と右端サイズMが接続されている所定の頂点、エッジ及び点のN -最も一般的な方法は、入力1を使用することです。
NM
U1 W1 V1
、U2、V2、W2の
...
UM VM WM
もし少し右に、行Nの数により各点の重みを示す値の典型的サイズ
P1 P2 ... PN
これは、隣接行列ストレージの最も簡単な図です。
図nの点、双方の間に接続されている場合はN×Nの二次元アレイを記録すると、右側のサイズ。
空間複雑度はO(n ^ 2)
場合によってはない側は、等、特別な値0または-1を使用することが可能でも、∞を使用しなくてもよいがある場合には。
複数のエッジが存在する場合には、そのまま情報全ての面でなくてもよいです。
隣接リストは、より一般的なストレージ図です。
各点uがその出発形状<U、V>そのようなアレイまたはリンクされたリスト記憶の長さなどのすべての側面を、不定。
双方向双方向の側縁のない分割ビューません。
可変長配列
リスト
宇宙複雑さO(N + M)
図トラバーサル方法:
BFSのBFSキュー
DFSスタック深さ優先探索
BFSの幅優先トラバーサルは、
各ノードへのアクセスの特定の順序に従ってキューを実装しました。
開始点を含むキューを作成します
最初のチームのノードを削除し、隣接ノードがキューにエンキューされていません
すべてのノードがトラバースされるまで、前の手順を繰り返します
マップ上の単一ソース最短経路問題のためには、権利はありません
DFSの深さ優先トラバーサル
各アクセスノードのための特定の順序に応じて、スタック(再帰関数)を用いて達成しました。
出発点sからトラバース
Uを横断するとき、再帰的にすべての隣接ノードをvアクセスされていない横断
sの出口機能を横断するときは、すべてのノードがトラバースされています
BFSとDFSトラバーサル方法は、両方に基づいており、図より基本的なトラバース法の最も基本的なものです
BFSとDFSは、図の通信要求や通信サブ図を決定するために使用することができます。
どちらも、実際の状況に応じて選択されるように、長所と短所を持っています
知識検索と組み合わせること
DFSオーダーの三種類
先行順走査
予約限定!
その後のトラバーサル
いくつかの簡単な例
例1
1.有向グラフを考えると、右側がシングルソースが最短シーク、1又は2です。
(未使用・フロイド、dijkstar、spfaなど)
[開く3つのキュー、まず距離のすべては、キュー内の0で、キュー場合は、すべてのポイントに一時的なポイントを列挙し、投写距離が距離2 2である場合、1の距離を投げますキュー
3のセットを作成し、Q0は、現在の層を表し、層1は、Q1の距離を表し、Q2は、距離層2、= {S}初期Q0、Q1 =∅、Q2 =∅を表します
順次Q1またはQ2に隣接点に対応配置されている点Q0を抽出します
そして、Q0 = Q1、Q1 = Q2、Q2 =∅
ポイントは、現在の層と1の辺の長さの両方であってもよいし、2辺の長さを有していることに注意し、それは、Q1がQ2を追加すべきではありません。
例2
各エッジのための有向グラフと始点Sを、与えられた<U、V> SからV最短経路長に、この縁部は、変更される場合は省略答え。無力;
dは[V]、D [U] +1、説明は道路の最短の辺である。= IF BFSは、エッジ用の<U、V>各ポイントのための単一始点最短D [i]は、開始点Sから再びシーク、保存;
> = 2の侵入点は、それが変更されないか、変更され
トポロジカルソート
有向非巡回グラフトポロジカルソートは、リニアシーケンスのすべての頂点を排出しようとしている、任意の<U、V>∈Eため、Uは直鎖状配列がVの前に発生有するように。
リングがある場合、トポロジカルソートは、図には存在してはならない。シクロない場合は、トポロジカルソートがあります。
Uの程度と呼ばれるポイントを選択0
リニアシーケンスの最後のuに追加します
Uのすべてを削除することによって、アウトサイド
すべてのポイントがシーケンスに追加されるまで、上記の手順を繰り返し
例1
n個のタスクは、m個の制約があり、UIタスクi番目のタスクviの前に完了しなければならない制限があります。私はすべての制限を満たすために、適切なタスクの実行順序があるかどうかを尋ねます。
点として各タスクは、タスク間の依存関係は、有向エッジを構成します。図面、そこトポロジカル整列へのループが存在しない場合は、トポロジカルソートが可能タスクの実行順序で、図面にリング、ノー溶液の存在場合。
例2
n個のタスクがありますが、m個の制限は、次の2つの制限があります。
Vタスクは、タスクのuを実行する前に完了しなければなりません
時間、uとvは、タスクの実行にありますされます
私は、制約のすべてを満たすためのソリューションの各タスクの開始時刻と終了時刻のスケジュールがあるかどうかを尋ねます
各セグメントについて、二つの点で表されます。実際に、それは時間、時間の終わりのための1つを表し、
タスク1については、それがあっても、Vの終了時点までの時間のU側を開始点まで、です。
2のためのタスクの後、uは、vの終了後の時間までの時間を開始し、V Uの終了時刻である必要があり、時間を開始。
各セグメントについてだけでなく、セグメントの終点は、この点ともエッジから開始します。
例3
右バンドエッジ有向非巡回グラフのために、単一ソース最短シーク。
私はディにトポロジカルソートする$ A_1、A_2、...、A_tと、S、B_1、B_2、...、B_k $、最短音符のポイントのような形、始点Sと呼ば。
\(D [V] = \ \限界分_ {<U、V>∈E} \ {D [U] + W_ {U、V} \} \)
S出発から来ることができない\(A_1、A_2、...、A_tと\)これらの点の最短されている、∞
从 s 出发走到 bi 之前一定只经过 \(b_1, b_2, . . . , b_{i-1}\),即 dbi 的求解依赖于 \(d_{b_1}, d_{b_2}, . . . , d_{b_{i-1}}\)
按顺序依次求解 ds, db1, db2, . . . , dbk 即可
POJ 1094 Sorting It All Out
An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B,C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specifed or not.
由一些不同元素组成的升序序列是可以用若干个小于号将所有的元素按从小到大的顺序 排列起来的序列。例如,排序后的序列为 A, B, C, D,这意味着 A < B、 B < C 和 C < D。在本题中,给定一组形如 A < B 的关系式,你的任务是判定是否存在一个有序序列。输出到哪一项可以确定顺序或者在这一项最先出现冲突,若所有的小于关系都处理完了都不能确定顺序也没有出现冲突,就输出不能确定。
冲突:拓扑排序排不出来就是冲突的(有环);
拓扑排序时,队列中永远没有出现大于一个元素的时候,就是唯一确定的;
不确定时,即队列中有时有>1个点;
BZOJ 2200 道路和航线
FJ 正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到 T 个城镇 (1 ≤ T ≤ 25000),编号为 1 到 T。这些城镇之间通过 R 条道路 (1 ≤ R ≤ 50000) 和 P 条航线(1 ≤ P ≤ 50000) 连接。每条道路 i 或者航线 i 连接城镇 Ai 到Bi,花费为 Ci。对于道路, 0 ≤ Ci ≤ 10000; 然而航线的花费很神奇,花费 Ci 可能是负数 (-10000 ≤ Ci ≤ 10000)。道路是双向的,可以从 Ai 到 Bi,也可以从 Bi 到 Ai,花费都是 Ci。然而航线与之不同,只可以从 Ai 到 Bi。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台了一些政策保证:如果有一条航线可以从 Ai 到 Bi,那么保证不可能通过一些道路和航线从 Bi 回到Ai。(有向边不存在于任何一个环,环都是正权无向边)由于 FJ 的奶牛世界公认〸分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇 S 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。 (求从s出发到某个点的单源最短路);O(nlogn)
把所有无向边加进去,形成若干连通块,看成一个大的点,然后加入有向边,形成一个DAG,如果有连通块的入度为0,直接连通块内跑dijkstar,有向边按拓扑序dp,更新dis,连通块内部使用dijkstar来做;
注意到如果有一条航线可以从 Ai 到 Bi,那么保证不可能通过一些道路和航线从 Bi 回到 Ai。
换言之,不存在包含航线(负权单向边)的环。
首先加入所有正权无向边,找出所有连通块,每个连通块缩为一个点。再加入所有单向边,此时图一定为 DAG。
在 DAG 上用 BFS 更新最短路,在正权无向边组成的连通块(缩点)内部使用 Dijkstra 更新最短路。
最短路
全局最短路 Floyd
单源最短路 Dijkstra SPFA Bellman-Ford
Floyd
基于动态规划, Fk,u,v, 表示使用点 1, 2, . . . , k 时,点 u 到点v 的最短路
从小到大枚举 k, u 和 v 之间的最短路要么不经过 k,要么经过 k 一次且除此之外只包含前 k - 1 个点
\(F_{k,u,v} =min\{F_{k-1,u,v}, F_{k-1,u,k} + F_{k-1,k,v}\}\)
for(int k=1;k<=n;k++)//k要写外面!
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
f[k][i][j]=min(f[k][i][j],f[k-1][i][k]+f[k-1][k][j]);
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
易见,使用二维数组不断覆盖更新即可。
时间复杂度 \(O(N^3)\)
空间复杂度 \(O(N^2)\)
可以处理含有负权边的情况,如果含有负环,则存在 i 使得
\(F_{i,i} < 0\)。
传递闭包?
判断两点是否可达:
\(bool \ f[i][j]\)表示i到j是否可达:
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]|=f[i][k]&f[k][j];
预防毒瘤出题人:
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)if(f[i][k])
for(int j=1;j<=n;j++)if(f[k][j])
f[i][j]=true;
Dijkstar
适用于没有负权边的图。
将所有点分为两个集合,最短路确定的集合 S 和最短路未确定的集合 T,初始 S ={s}
求 T 中每个点 v 的当前最短路
\(d_v=\min_{<u,v>∈E,u∈S}\{d_u + w_{u,v}\}\)
取出 T 中 \(d_v\) 最小的点,其最短路一定就是 \(d_v\),将其加入 S
不断重复上面的操作,直到所有点的最短路都确定
朴素写法时间复杂度较劣,可以采用堆优化至$ O((N + M)logN) $
using pii=pair<int,int>
priority_queue<pii,veector<pii>,greater<pii> > q;
void dijkstar(){
memset(dis,inf,sizeof(dis));
q.push(make_pair(dis[s]=0,s));
while(!q.empty()){
int u=q.top().second;
int d=q.top().first;
q.pop();
if(d!=dis[u]) continue;
for(int i=head[u],v,w;i;i=edge[i].next){
if(v=to[i],w=edge[i].dis,dis[v]>d+w)
q.push(make_pair(dis[v]=d+w,v));
}
}
}
Bellman-Ford
初始令 \(d_s\) = 0,其余 \(d_i\) = ∞
依次使用每一条边 < u, v > 更新,$ d_v = min{d_v, d_u + w_{u,v}}$
不断循环直到所有 \(d_i\) 都不会更新
因为任何一条最短路包含至多 n - 1 条边,没有负环则不超过 n 轮就会停止
时间复杂度 O(NM)
空间复杂度 O(N + M)
可以对包含负权边的图使用,如果存在负环,则循环超过 n 轮后依然不会停止,可以用来判断负环是否存在。
SPFA
考虑使用队列优化 Bellman-Ford 算法,如果更新了 \(d_u\),则将 u入队。每次取队首 u 更新其邻点 v 的 \(d_v\)。
最差复杂度O(NM);