图论

图论
风铃夜行图论
常见概念
oriented graph:有向图
bidirectional edges:双向边
平面图:若能将无向图
无向正权图上某一点的偏心距:记为
图的直径:定义为
图的中心:定义为
图的绝对中心:可以定义在边上的图的中心。
图的半径:图的半径不同于圆的半径,其不等于直径的一半(但对于绝对中心定义上的直径而言是一半)。定义为

平面图性质
一、定义
- 图G可嵌入平面: 如果可以把图G的所有结点和边都画在平面上,同时除断点外连线之间没有交点,就称图G可嵌入平面。画出的无边相交的G’称G的平面嵌入。
- 可平面化: 如果图G可以嵌入平面,就称图G可平面化。
- 面: G中边所包含的区域称作一个面。有界区域称为内部面,无界区域称为外部面,常记作
,包围面的长度最短的闭链称为该面的边界,面 的边界的长度称为该面的度数,记作 。 - 面的度数计算: 含有割边和桥的度数为2,其余为1。
二、性质
- 性质 1.
均为极大可平面图. - 性质 2. 极大平面图必是连通图.
- 性质 3. 当图阶数
时, 有割点或者桥的平面图不是极大平面图.
三、定理
- 定理 1: 图
可嵌入球面当且仅当图 可嵌入平面。 - 定理 2:
中各面的度数之和等于图 边数的两倍。
证明: 设为图 的两个面的公共边,再计算两个面的度数时候边数各提供1,当 不是公共边时候,也就是 为桥或者割边时候提供度数为2。因此,面的度数之和为边的两倍。 - 定理 3: 设
是图 的某个平面嵌入的一个内部面,则存在图 的一个平面嵌入使 为外部面。 - 定理 4: 设图
是简单的可平面图,如果 中任意两个不相邻的结点加边后所得到的为非可平面图。则称 是极大可平面图,极大可平面图的任何平面嵌入都称为极大平面图。极大平面图必是连通图。 - 定理 5: 图
为 阶简单的连通的平面图, 为极大平面图当且仅当 的每一个面的度数为3。
定理说明: 结点数大于等于3的极大平面图的任何面都是由三角形组成。 - 定理 6:欧拉公式: 设图
是有 个结点、 条边和 个面的连通平面图,则它们满足:
四、结论
- 结论 1:
( 任意删去一条边)均为极大可平面图,它们的任何平面嵌入都是极大平面图;当阶数等于3时候,有割边或桥的平面图不可能是极大平面图。 - 结论 2: 无向完全图
和无向完全二部图 都是极小非可平面图(去掉一条边就成为可平面图)。 - 结论 3: 一个图是可平面图,那么它的子图也是可平面图;一个图的子图是非可平面图,那么图本身也是非可平面图。
- 结论 4: 同一个图的平面嵌入中,外部面和内部面的度数可以不同。
五、推论
- 推论 1: 设图
是有 个结点、 条边的连通平面简单图,其中 ,则有:
证明: 由图的面度数之和为边数的二倍,即 。又因为 是平面简单图每一个面的度数至少为3,则 ,由欧拉公式有: - 推论 2: 设图
是有 个结点、 条边的连通平面简单图,其中 且没有长度为3的圈,则有:
证明:没有长度为3的圈也就没有度为3的面, 的每一个面的度数至少为4。所以 ,由欧拉公式有:
提示: 对于推论1和推论2我们可以用定理进行判定它不是平面图。
例 1: 证明和 是非平面图。
证明:- 在
中, 应该小于等于 ,即 。而完全图 具有10条边。所以是非平面图。 - 在
中,没有长度大于3的圈,根据推论2可知, ,也就是 ,而 含有9条边,所以是非平面图。
- 在
- 推论 3: 设
是连通的平面图, 且每个面的度数至少为 , 则
证明: 同理,有,根据欧拉公式化简得: - 推论 4: 设
是平面图, 有 个连通分支, 个结点, 条边, 个面, 则公式
成立. - 推论 5: 设
是有 个结点、 条边和 个面、 个连通分支的平面图, 且 的各个面的度数至少为 , ( ), 则
证明: 证明过程与推论3类似,用到推论4的结论。 - 推论 6: 设
是任意平面简单图, 则
证明: 设有 个顶点 条边. 若 , 结论显然成立; 若 , 假设 的每个顶点的度数 , 则由推论 1, 有
与定理矛盾, 故.
六、判别定理
- 极大平面图的判别定理:
阶连通的简单平面图 . 则以下四个条件等价: 是极大平面图; 中每个面的度数都是3; 中有 条边 个面, 则 - 设
带有 个顶点, 条边, 个面则
单源最短路径(SSSP问题)
(正权稀疏图)动态数组存图+Djikstra算法
使用优先队列优化,以
1 | vector<int> dis(n + 1, 1E18); |
(负权图)Bellman ford 算法
使用结构体存边(该算法无需存图),以 d[end]
的值更新),该性质可以用于判断路径上是否存在负环:在
下方代码例题:求解从
1 | const int N = 550, M = 1e5 + 7; |
(负权图)SPFA 算法
以
1 | const int N = 1e5 + 7, M = 1e6 + 7; |
(正权稠密图)邻接矩阵存图+Djikstra算法
很少使用,以
1 | const int N = 3010; |
多源汇最短路(APSP问题)
使用邻接矩阵存图,可以处理负权边,以
1 | const int N = 210; |
平面图最短路(对偶图)
对于矩阵图,建立对偶图的过程如下(注释部分为建立原图),其中数据的给出顺序依次为:各
1 | for (int i = 1; i <= n + 1; i++) { |
最小生成树(MST问题)
(稀疏图)Prim算法
使用邻接矩阵存图,以
1 | const int N = 550, INF = 0x3f3f3f3f; |
(稠密图)Kruskal算法
平均时间复杂度为
1 | struct DSU { |
缩点(Tarjan 算法)
(有向图)强连通分量缩点
强连通分量缩点后的图称为 SCC。以
性质:缩点后的图拥有拓扑序
,可以不需再另跑一遍 ;缩点后的图是一张有向无环图( 、拓扑图)。
1 | struct SCC { |
(无向图)割边缩点
割边缩点后的图称为边双连通图 (E-DCC),该模板可以在
割边(桥):将某边
删去后,原图分成两个以上不相连的子图,称 为图的割边。 边双连通:在一张连通的无向图中,对于两个点
和 ,删去任何一条边(只能删去一条)它们依旧连通,则称 和 边双连通。一个图如果不存在割边,则它是一个边双连通图。 性质补充:对于一个边双,删去任意边后依旧联通;对于边双中的任意两点,一定存在两条不相交的路径连接这两个点(路径上可以有公共点,但是没有公共边)。
1 | struct EDCC { |
(无向图)割点缩点
割点缩点后的图称为点双连通图 (V-DCC),该模板可以在
割点(割顶):将与某点
连接的所有边删去后,原图分成两个以上不相连的子图,称 为图的割点。 点双连通:在一张连通的无向图中,对于两个点
和 ,删去任何一个点(只能删去一个,且不能删 和 自己)它们依旧连通,则称 和 边双连通。如果一个图不存在割点,那么它是一个点双连通图。 性质补充:每一个割点至少属于两个点双。
1 | struct V_DCC { |
染色法判定二分图 (dfs算法)
判断一张图能否被二分染色。
1 | vector<int> vis(n + 1); |
链式前向星建图与搜索
很少使用这种建图法。
1 | namespace Graph { |
一般图最大匹配(带花树算法)
与二分图匹配的差别在于图中可能存在奇环,时间复杂度与边的数量无关,为
1 | struct Graph { |
一般图最大权匹配(带权带花树算法)
下方模板编号从
1 | namespace Graph { |
二分图最大匹配
二分图:一个图能被分为左右两部分,任何一条边的两个端点都不在同一部分中。
匹配(独立边集):一个边的集合,这些边没有公共顶点。
二分图最大匹配即找到边的数量最多的那个匹配。
一般我们规定,左半部包含
个点(编号 ),右半部包含 个点(编号 ),保证任意一条边的两个端点都不可能在同一部分中。
匈牙利算法(KM算法)解
1 | signed main() { |
HopcroftKarp算法(基于最大流)解
该算法基于最大流,常数极小,且引入随机化,几乎卡不掉。最坏时间复杂度为
1 | struct HopcroftKarp { |
二分图最大权匹配(二分图完美匹配)
定义:找到边权和最大的那个匹配。
一般我们规定,左半部包含
个点(编号 ),右半部包含 个点(编号 )。
使用匈牙利算法(KM算法)解,时间复杂度为
1 | struct MaxCostMatch { |
二分图最大独立点集(Konig 定理)
给出一张二分图,要求选择一些点使得它们两两没有边直接连接。最小点覆盖等价于最大匹配数,转换为最小割模板,答案即为总点数减去最大流得到的值。
1 | cout << n - flow.work(s, t) << endl; |
最长路(topsort+DP算法)
计算一张
1 | struct DAG { |
最短路径树(SPT问题)
定义:在一张无向带权联通图中,有这样一棵生成树:满足从根节点到任意点的路径都为原图中根到任意点的最短路径。
性质:记根节点
到某一结点 的最短距离 ,在 上这两点之间的距离为 ——则两者长度相等。
该算法与最小生成树无关,基于最短路
1 | map<pair<int, int>, int> id; |
无源汇点的最小割问题 Stoer–Wagner
也称为全局最小割。定义补充(与《网络流》中的定义不同):
割:是一个边集,去掉其中所有边能使一张网络流图不再连通(即分成两个子图)。
通过递归的方式来解决无向正权图上的全局最小割问题,算法复杂度
1 | signed main() { |
欧拉路径/欧拉回路 Hierholzers
欧拉路径:一笔画完图中全部边,画的顺序就是一个可行解;当起点终点相同时称欧拉回路。
有向图欧拉路径存在判定
有向图欧拉路径存在:
1 | signed main() { |
无向图欧拉路径存在判定
无向图欧拉路径存在:
1 | signed main() { |
有向图欧拉路径求解(字典序最小)
1 | vector<int> ans; |
无向图欧拉路径求解
1 | auto dfs = [&](auto self, int x) -> void { |
差分约束
给出一组包含
1 | signed main() { |
2-Sat
基础封装
基于 tarjan 缩点,时间复杂度为
1 | struct TwoSat { |
答案不唯一时不输出
在运行后针对每一个点进行一次 dfs,时间复杂度为 ?
替代。
2-Sat方案计数为 NPC 问题。
1 | // 结构体中增加 |