OI集训 Day25
Content:图论基础
Date:2025.8.10
课堂内容
图论基础知识
- 图的定义:由点集 和边集 组成,记作图 。
- 阶:图的点数,记作 。
- 相邻:称图中的两个点 相邻,当且仅当 。
- 连通:无向图中若存在 的路径则称 连通。
- 弱连通:若有向图变为无向图后 连通,则称 弱连通。
- 连通图:无向图中任意两点连通的图称作连通图。
- 弱连通图:有向图中任意两点弱连通的图称作弱连通图。
- 简单图:不存在重边和自环的图。
- 稀疏图/稠密图: 的图称作稀疏图, 接近 的图称作稠密图。
拓扑排序
Problem
给定一个有向无环图(DAG),要求求出一个序列 ,其中 在排列 中的位置记作 ,则这个序列满足满足:
- ,。
Solution
每次从 DAG 中选择一个入度为 0 的点,将这个点加入序列 中,然后删掉这个点和这个点在图中的所有出边,重复这个过程。
Proof
显然对于任意的 ,点 总是在 之前被加入序列 ,所以最后得到的学列一定是合法的。复杂度为 。
Extend
可以用拓扑排序判断一个有向图是否存在环。
最短路算法
Problem 1
给定一张图和一个源点 ,求图上所有点到源点 的最短距离 。
Solution
Bellman-Ford
松弛操作:称一次松弛操作为对于每一条边 ,用 。
这样进行松弛操作 轮就可以得到 。复杂度为 。
Extend: Bellman-Ford 算法也可以用来判断图中是否存在负环。如果进行了 轮松弛操作后依然存在可以被更新的 ,则图中一定存在负环。因为在这个操作中负环被视为无穷小而被无限更新下去。
SPFA
关于 SPFA,它死了。
松弛点 时若存在可以用 更新的 且 不在队列中,则将 压入队列,重复这个过程知道队列为空。复杂度 。
Extend:和 bellman-ford 一样,如果存在点被压入队列超过 次,则图中存在负环。
Dijkstra
扩展:对于一个点 ,称扩展点 表示用 的所有出边 更新 。
每次选择未被扩展的 最小的点 进行扩展,可以用 优先队列 将复杂度优化到 ,但只能处理 非负权图。
Problem 2
对于一个给定的图,求图中任意两点的最短距离。
Solution
Johnson
从超级源点向所有点连一条 的边,跑一边 Bellman-Ford/SPFA 得到最短路 。然后改造边为 。然后再在新图上跑一边 Dijkstra(新图为非负权图),复杂度为 。
Floyd
初始化所有 ,然后在这个数组上进行如下更新:
实际上就是一个动态规划,复杂度为 。
最短路树
在单源最短路中,记录每个点最后被更新的前驱 ,以这个建边得到的树就是最短路树。
删边最短路
Problem
给定一个正权无向图,求删除每一条边后从 到 的最短路。
Solution
我们建立一个从 出发的最短路树 ,和一个到达 的最短路树 。容易发现若删除的边 不在原最短路上,则删除 不会影响答案。
所以我们不妨设原最短路为 ,找到所有满足 不在 的 的子树内, 不在 的 的子树内的所有边 。用 更新答案。复杂度可以用数据结构优化到 。
无向图连通性
定义
- 割边:删去后使得连通分量增加的边。
- 割点:删去后使得连通分量增加的点
- 点双连通图:不存在割点的无向连通图。
- 边双连通图:不存在割边的无向连通图。
- 点双连通分量:极大点双连通子图,即 V-BCC。
- 边双连通分量:极大边双连通子图,即 E-BCC。
性质
点双连通分量
- 若两个点双连通分量有交点,则这个交点有且仅有一个,且为割点。
- 一个点是割点当且仅当它属于超过一个边双连通分量。
- 一条边仅属于一个点双连通分量。
- 由一条边直接连接的两个点 点双连通。
- 点双内任意一个点 均存在经过这个点的简单环。
- 点双内任意一个点对 ,均存在包含这个点对的简单环。
边双连通分量
- 两个点之间任意一条 迹 上的所有割边就是这两个点的必经边。
- 若 和 边双连通, 和 边双连通,则 和 边双连通(传递性)。
- 和 之间边双连通当且仅当这两个点之间的必经边集合为空。
- 对于一个边双连通分量中的任意一条边 ,均存在经过这条边的回路。
- 边双内任意一点均存在经过这个点的回路。
- 边双内任意一组点对 均存在包含这个点对的回路。
求解
有向图连通性
定义
- 强连通:一个点对 互相可达。
- 强连通图:图中任意两点互相可达的有向连通图。
- 强连通分量:极大的强连通子图,即 SCC。
性质
- 若 ,则 可达 当且仅当 可达 。
- 若 强连通,则 在 dfs 树上路径的所有点弱连通。
- 强连通分量在 dfs 树上弱连通。
求解
- 强连通分量(Tarjan):Link
最小生成树
定义
- 生成树:对于连通图而言,生成树是原图一个树形结构的生成子图。
- 生成森林:每一个连通分量的生成树组成的子图。
求解最小生成树
Kruskal
首先对原图的边按照边的权值从小到大排序,然后枚举每一条边,如果这条边连接的两个点现在并不连通,则将这一条边加入最小生成树。连通性可以用并查集维护,复杂度为 。
实现:Link
Prim
类似 Dijkstra,每次选择一个现在在最小生成树上的点 ( 为当前已经加入最小生成树的点集),将满足 且 最小的边加入最小生成树。用优先队列可以把复杂度优化到 。
实现:Link
例题
Luogu-P1967 [NOIP 2013 提高组] 货车运输
题目大意
给定一张由 个点 条双向边组成的无向带权图,有 次询问,每次询问 之间的最大瓶颈路。
思路
首先如果对于每次询问都单独跑一边 Dijkstra 的复杂度是 的,显然不可接受。
我们发现由于题目要求的是瓶颈路,所以很多边都是用不到的。更进一步的,我们发现只有原图中 最大生成树 上的边才是有用的。所以我们可以对于原图的最大生成树重新建边,然后这个问题就转化为了树上问题。
转化为树上问题后, 的路径很显然可以分为 和 ,所以就转化为了求树上两个点之间路径上的最小权值。可以用倍增求 ,复杂度为 。
提交记录:Link

