基本概念
图的基本概念
图 (Graph) 是由若干给定的顶点及连接两顶点的边所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系。顶点用于代表事物,连接两顶点的边则用于表示两个事物间具有这种关系。
图是一个二元组\(G=(V(G),E(G))\),其中 \(𝑉(𝐺)\) 是非空集,称为点集或阶,对于\(V\)中的每个元素,我们称其为 顶点 (vertex) 或 节点 (node),简称点;\(E(G)\)为\(V(G)\)各结点之间边的集合,称为 边集 (edge set)。
常用\(G=(V,E)\)表示图。
图的种类
有向图、无向图和混合图
有向图指图中的边是有方向的,无向图则反之。如果一个图中既有无向边,也有有向边,则称为混合图。
若\(G\)为无向图,则\(E\)中的每个元素为一个无序二元组\((u,v)\)。
若\(G\)为有向图,则\(E\)中的每个元素为一个有序二元组组\((u,v)\)。设组\(e=u→v\),则此时\(u\)称为\(e\)的起点(tail),\(v\)称为\(e\)的终点(head),\(e\)也叫做弧。
边通常用箭头表示,而箭头是从「尾」指向「头」的。
因此,起点是 tail,终点是 head。
加权图(赋权图)
即图中的边具有权值,也分为加权有向图和加权无向图。
如果所有的权值都是正数,也可以叫做正权图。
有限图和无限图
当\(V\)或\(E\)是无限集合时,称图为无限图;当\(V\)或\(E\)都是有限集合时,称图为有限图。
度
与一个顶点\(v\)关联的边的条数称作该顶点的 度 (degree),记作\(d(v)\)。特别地,对于边 \((v,v)\),则每条这样的边要对 $𝑑(𝑣) \(产生\)2$的贡献。
在无向图中,连接该节点的边的条数即为该顶点的度数。
在有向图中,分为出度和入度,分别表示从该顶点出发的边的条数,和指向该节点的边的条数。
由度衍生出了以下概念:
- 孤立点:若\(𝑑(𝑣) =0\),则称\(v\)为 孤立点 (isolated vertex)
- 叶节点(悬挂点):若 \(𝑑(𝑣) =1\),则称\(v\)为 叶节点 (leaf vertex)/悬挂点 (pendant vertex)。
- 偶点:若 \(2|d(v)\),则称 \(v\) 为 偶点 (even vertex)
- 奇点:若\(2 ∤𝑑(𝑣)\),则称\(v\)为 奇点 (odd vertex)。图中奇点的个数是偶数(详见握手定理)。
相邻
对于无向图,如果两个顶点间有边相连,则称这两个点是相邻的,而这条边分别和这两个点关联。其中,一个顶点的邻域是所有与它相邻的顶点构成的集合,记作\(N(v)\);一个点集\(S\)的的邻域是所有与\(S\)中至少一个点相邻的点构成的集合,记作\(N(S)\):
对于有向图,相邻的概念划分得更加具体。给定有向图中的边\(e=u→v\):
- 对于\(u\),我们称\(u\)邻接于\(v\),这表示\(u\)是起点,是\(v\)的入邻点。
- 对于\(v\),我们称\(v\)从\(u\)邻接,这表示\(v\)是终点,是\(u\)的出邻点。
对于邻点,入邻点的集合通常记作\(N^-(v)\),出零点的集合通常记作\(N^+(v)\)。
简单图
若一个图中不存在自环和重边,则称其为简单图。
根据鸽巢原理,至少有两个顶点的简单无向图中,一定存在度相同的点。
自环
对于\(E\)中的边\(e=(u,v)\),若\(u=v\),则\(e\)被称作一个自环(Loop)。
自环即两个顶点是同一个点的边,尽管在理论看来定义它似乎多此一举,但它在实践中存在意义,如在状态机中表示状态不变。
重边
若\(E\)中存在两条完全相同的边,则它们是一组重边。
路径
-
途径:途径(Walk)是连接一连串顶点的边的序列,可以是有限或无线长度。
通常来说,途径的长度是组成途径的边的数量;如果是赋权图,则是边的权值之和。
- 迹:如果组成一条途径的边均不重复,则称这条途径为迹(Trail)。
- 路径:如果一条迹连接的所有点中没有重复的,则称这条迹是路径(Path)。
- 回路:如果一条迹的长度为k,连接的端点集合\(V\)中有\(v_0=v_k\),则称这条迹是一条回路(circuit)。
- 环:对于一条回路,如果\(v_0=v_k\)是集合\(V\)中唯一重复出现的点对,则称这条回路是一个环。
子图
对于图\(G=(V,E)\),若存在另一张图\(H=(V',E')\)满足\(V' ⊆V\)且\(E'⊆E\),则称\(H\)是\(G\)的子图。
导出子图(诱导子图)
若\(H\)是\(G\)的子图,\(E'\)包含且仅包含\(E\)中两个顶点都在\(V'\)中的边,则称\(H\)是\(G\)的导出子图。
导出子图由点决定,即在已知原图\(G\)和导出子图的点集\(V'\)的情况下,就可以确定\(E'\)。
生成子图(支撑子图)
若\(H\)是\(G\)的子图,且\(V=V'\),则称若\(H\)是\(G\)的生成子图。
显然,对于任意图\(G\)都有:\(G\)是自身的子图、支撑子图和导出子图。
连通性
对于有向图和无向图,连通性的定义有所区别。
无向图
对于无向图\(G=(V,E)\),其中\(u,v∈𝑉\),若存在一条途径使得\(v_0=u\),\(v_k=v\),则称\(u\)和\(v\)是连通的。
如果无向图\(G\)满足任意两个顶点均连通,则称\(G\)是连通图,称\(G\)具有连通性。
若\(H\)是\(G\)的一个连通子图,且不存在连通图\(F\)满足\(𝐻 ⊊𝐹 ⊆𝐺\),则称\(H\)是\(G\)的一个连通分量(极大连通子图)。
有向图
对于有向图\(G=(V,E)\),其中\(u,v∈𝑉\),若存在一条途径使得\(v_0=u\),\(v_k=v\),则称\(u\)可达\(v\)的。
如果有向图\(G\)满足任意两个顶点均两两互相可达,则称\(G\)是连通图,称\(G\)是强连通的。
如果有向图\(G\)不是强连通的,但将所有边替换为无向边后,得到一张连通图,则称\(G\)是弱连通的。
和无向图一样,有向图有弱连通分量(极大弱连通子图),和强连通分量(极大强连通子图)。
图的存储
在代码中,一般使用邻接表、邻接矩阵或类表示。
在本篇中,规定\(n\)表示图的端点数目,\(m\)表示图的边数目,\(d^+(u)\)表示点\(u\)的出度。
朴素存储
参考代码
朴素存储即直接存边,使用一个数组存储所有的边,每个元素包括边的起点、终点和权值(如果存在)。
朴素存储的复杂度如下:
- 查询是否存在某条边:\(O(m)\)
- 遍历一个点的所有出边:\(O(m)\)
- 遍历整张图:\(O(nm)\)
- 空间复杂度:\(O(m)\)
朴素存储的遍历效率较低,通常不会使用。
邻接矩阵
参考代码
邻接矩阵使用\(n \cdot n\)的二维数组表示图结构,这是从节点的角度来表示图的思路。
其中,g[u][v]为1表示存在\(u\)到\(v\)的边,为0表示不存在。如果是带边权的图,可以在g[u][v]中存储\(u\)到\(v\)的边权。
邻接矩阵的复杂度如下:
- 查询是否存在某条边:\(O(1)\)
- 遍历一个点的所有出边:\(O(n)\)
- 遍历整张图:\(O(n^2)\)
- 空间复杂度:\(O(n^2)\)
邻接矩阵只适用于没有重边(或重边可忽略)的情况,显著优点是查询某条边只需要\(O(1)\)时间。
邻接矩阵在稀疏图上表现较差,空间浪费的问题非常严重,因此一般只会在稠密图上使用。
邻接表
参考代码
邻接表使用数组+vector来表示图结构:使用一个数组存储所有点,数组的每个元素是一个存储对应点出边的vector。
邻接表的复杂度如下:
- 查询是否存在某条边:\(O(d^+(u))\),如果事先进行了排序就可以使用做到\(O(\log (d^+(u))\)
- 遍历一个点的所有出边:\(O(d^+(u))\)
- 遍历整张图:\(O(m+n)\)
- 空间复杂度:\(O(m)\)
邻接表在点数较少的图中需要快速查询一条边是否存在时,表现较为劣势,这种情况可以使用邻接矩阵。
除此以外,邻接表是一种较为通用的方法,尤其适用于需要对一个点的所有出边进行排序的场合。
链式前向星
参考代码
链式前向星本质是链表实现的邻接表,使用链表存储每个点的出边。
链式前向星的复杂度如下:
- 查询是否存在某条边:\(O(d^+(u))\)
- 遍历一个点的所有出边:\(O(d^+(u))\)
- 遍历整张图:\(O(m+n)\)
- 空间复杂度:\(O(m)\)
链式前向星的缺陷在于不能快速询问一条边是否存在,也不能在方便地对一个点的出边进行排序。
链式前向星依赖一个存储每个点的入口(即其出边链表的首个节点)的整型数组和一个存边的结构体数组实现。
其中,结构体的定义如下:
其中edge的大小由题目规定的边的最大数目决定。
对于无向图,
edge数组的大小应该开到边的最大数目*2。
为了便于存储,定义以下方法新增边:
对于无向图,应该调用两次
add_edge()方法,即add_edge(u,v)和add_edge(v,u)。
需要注意,cnt和head都应该手动初始化为\(0\) :
遍历出边时,方法和遍历链表一致:
树的基本概念
主要概念见树基础 - OI Wiki,此处只整理其它理论的前置或引用内容。
生成树
生成树是一个针对连通图的特定子图,它保留了原图的所有点,同时保证没有任何环。
其中,最小生成树仅针对带边权的图,指在所有生成树中边权和最小的一个。
推论与定理
握手定理
给定任意图\(G=(V,E)\),由于图每条边实际上都由两个顶点连接而成,因此任意图的度数之和必定为\(2E\),奇点的个数必定为偶数,记作: