保研考研机试攻略:第七章——图论(1)

🍨🍨🍨这一章,我们来重点看一些常见的图论题型,包括图的理论基础、图的存储、并查集、最小生成树问题、最短路径问题、拓扑排序等内容。希望能帮助大家更好地掌握计算机考研机试中所涉及到的图论问题。fighting!( •̀ ω •́ )✧

目录

[🧊🧊🧊7.1 理论基础](#🧊🧊🧊7.1 理论基础)

一、顶点(vertex)

二、边(edge)

[三、同构(Isomorphism )](#三、同构(Isomorphism ))

[四、有向/无向图(Directed Graph/ Undirected Graph)](#四、有向/无向图(Directed Graph/ Undirected Graph))

五、权重(weight)

[六、路径/最短路径(path/shortest path)](#六、路径/最短路径(path/shortest path))

七、环(loop)

[八、连通图/连通分量(connected graph/connected component)](#八、连通图/连通分量(connected graph/connected component))

九、有向图/无向图的度数

[🧊🧊🧊7.2 图的存储](#🧊🧊🧊7.2 图的存储)

邻接矩阵

邻接表

两者区别

[🧊🧊🧊6.3 并查集](#🧊🧊🧊6.3 并查集)

[🥥例题:DreamJudge 1319](#🥥例题:DreamJudge 1319)


🧊🧊🧊7.1 理论基础

对于大部分图论问题,直接套算法模板即可。

一、顶点(vertex)

上图中黑色的带数字的点就是顶点,表示某个事物或对象。由于图的术语没有标准化,因此,称顶点为点、节点、结点、端点等都是可以的。叫什么无所谓,理解是什么才是关键。

二、边(edge)

上图中顶点之间蓝色的线条就是边,表示事物与事物之间的关系。需要注意的是边表示的是顶点之间的逻辑关系,粗细长短都无所谓的。包括上面的顶点也一样,表示逻辑事物或对象,画的时候大小形状都无所谓。

三、同构(Isomorphism )

先看看下面 2 张图:

这两个图直观看起来好像不太一样,但从图的角度出发,这 2 个图是一样的,即它们是同构的。前面提到顶点和边指的是事物和事物的逻辑关系,不管顶点的位置在哪,边的粗细长短如何,只要不改变顶点代表的事物本身,不改变顶点之间的逻辑关系,那么就代表这些图拥有相同的信息,是同一个图。同构的图区别仅在于画法不同。

四、有向/无向图(Directed Graph/ Undirected Graph)

最基本的图通常被定义为"无向图",与之对应的则被称为"有向图"。两者唯一的区别在于,有向图中的边是有方向性的。下图即是一个有向图,边的方向分别是:(1->2), (1-> 3), (3-> 1), (1->5), (2->3), (3->4), (3->5), (4->5), (1->6), (4->6)。要注意,图中的边(1->3)和(3->1)是不同的。有向图和无向图的许多原理和算法是相通的。

这个图有点问题,那个长方形块是箭头。

五、权重(weight)

边的权重(或者称为权值、开销、长度等),也是一个非常核心的概念,即每条边都有与之对应的值。例如当顶点代表某些物理地点时,两个顶点间边的权重可以设置为路网中的开车距离。

下图中顶点为 4 个城市:Beijing, Shanghai, Wuhan, Guangzhou,边的权重设置为 2 城市之间的开车距离。有时候为了应对特殊情况,边的权重可以是零或者负数,注意,"图"是用来记录关联的东西,并不是真正的地图。

六、路径/最短路径(path/shortest path)

在图上任取两顶点,分别作为起点(start vertex)和终点(end vertex),我们可以规划许多条由起点到终点的路线。不会来来回回绕圈子、不会重复经过同一个点和同一条边的路线,就是一条"路径"。两点之间存在路径,则称这 2 个顶点是连通的(connected)。

还是上图的例子,北京->上海->广州,是一条路径,北京->武汉->广州,是另一条路径,北京--->武汉->上海->广州,也是一条路径。而北京->武汉->广州这条路径最短,称为最短路径。

路径也有权重。路径经过的每一条边,沿路加权重,权重总和就是路径的权重(通常只加边的权重,而不考虑顶点的权重)。在路网中,路径的权重,可以想象成路径的总长度。在有向图中,路径还必须跟随边的方向。

值得注意的是,一条路径包含了顶点和边,因此路径本身也构成了图结构,只不过是一种特殊的图结构。

七、环(loop)

环,也成为环路,是一个与路径相似的概念。在路径的终点添加一条指向起点的边,就构成一条环路。通俗点说就是绕圈。

上图中,北京->上海->武汉->广州->北京,就是一个环路。北京->武汉->上海->北京,也是一个环路。与路径一样,有向图中的环路也必须跟随边的方向。环本身也是一种特殊的图结构。

八、连通图/连通分量(connected graph/connected component)

如果在图 G 中,任意 2 个顶点之间都存在路径,那么称 G 为连通图(注意是任意 2 顶点)。上面那张城市之间的图,每个城市之间都有路径,因此是连通图。而下面这张图中,顶点 8 和顶点 2 之间就不存在路径,因此下图不是一个连通图,当然该图中还有很多顶点之间不存在路径。

上图虽然不是一个连通图,但它有多个连通子图:0,1,2 顶点构成一个连通子图,0,1,2,3,4 顶点构成的子图是连通图,6,7,8,9 顶点构成的子图也是连通图,当然还有很多子图。我们把一个图的最大连通子图称为它的连通分量。0,1,2,3,4 顶点构成的子图就是该图的最大连通子图,也就 是连通分量。连通分量有如下特点:

1)是子图;

2)子图是连通的;

3)子图含有最大顶点数。

注意:"最大连通子图"指的是无法再扩展了,不能包含更多顶点和边的子图。0,1,2,3,4 顶点构成的子图已经无法再扩展了。

显然,对于连通图来说,它的最大连通子图就是其本身,连通分量也是其本身

九、有向图/无向图的度数

对于无向图,每个顶点的度数就是它连接边的数量

对于有向图,入度就是有向图的某个顶点作为终点的次数和;出度就是,有向图的某个顶点作为起点的次数和。

🧊🧊🧊7.2 图的存储

图有两种存储方式,邻接矩阵和邻接表。

邻接矩阵

图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息。

设图 G 有 n 个顶点,则邻接矩阵是一个 n*n 的方阵,定义为:


看一个实例,下边左图就是一个无向图:

从上面可以看出,无向图的边数组是一个对称矩阵。所谓对称矩阵就是 n 阶矩阵的元满足aij = aji。即从矩阵的左上角到右下角的主对角线为轴,右上角的元和左下角相对应的元全都是相等的。从这个矩阵中,很容易知道图中的信息。

(1)要判断任意两顶点是否有边无边就很容易了;

(2)要知道某个顶点的度,其实就是这个顶点 vi 在邻接矩阵中第 i 行或(第 i 列)的元素之

和;

(3)求顶点 vi 的所有邻接点就是将矩阵中第 i 行元素扫描一遍,arc[i][j]为 1 就是邻接点;

而有向图讲究入度和出度,顶点 vi 的入度为 1,正好是第 i 列各数之和。顶点 vi 的出度为 2,即第 i 行的各数之和。

邻接表

邻接矩阵是不错的一种图存储结构,但是,对于边数相对顶点较少的图,这种结构存在对存储空间的极大浪费。因此,找到一种数组与链表相结合的存储方法称为邻接表。

邻接表的处理方法是这样的:

(1)图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过,数组可以较

容易的读取顶点的信息,更加方便。

(2)图中每个顶点 vi 的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用单链

表存储,无向图称为顶点 vi 的边表,有向图则称为顶点 vi 作为弧尾的出边表。

例如,下图就是一个无向图的邻接表的结构。


从图中可以看出,顶点表的各个结点由 data 和 firstedge 两个域表示,data 是数据域,存储顶点的信息,firstedge 是指针域,指向边表的第一个结点,即此顶点的第一个邻接点。边表结点由 adjvex 和 next 两个域组成。adjvex 是邻接点域,存储某顶点的邻接点在顶点表中的下标,next 则存储指向边表中下一个结点的指针。

对于带权值的网图,可以在边表结点定义中再增加一个 weight 的数据域,存储权值信息即可。如下图所示。

两者区别

对于一个具有 n 个顶点 e 条边的无向图,它的邻接表表示有 n 个顶点表结点 2e 个边表结点

对于一个具有 n 个顶点 e 条边的有向图,它的邻接表表示有 n 个顶点表结点 e 个边表结点

如果图中边的数目远远小于 n 2称作稀疏图,这时用邻接表表示比用邻接矩阵表示节省空间; 如果图中边的数目接近于 n 2 ,对于无向图接近于 n*(n-1)称作稠密图,考虑到邻接表中要附加链域,采用邻接矩阵表示法为宜。

🧊🧊🧊6.3 并查集

并查集是解决集合类问题的,比如朋友关系,比如道路连通关系等等。

并查集本质是利用树形结构来加快区分集合的算法,这么一看,用 map 来区分也是可以的。但是并查集在树形结构的特点上加入了路径压缩的思想,使得算法效率远高于 map。

🥥例题:DreamJudge 1319

用并查集模板即可:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int fa[maxn];
//并查集模板
int find(int x) {
    if (x == fa[x]) return x;
    fa[x] = find(fa[x]); //路径压缩
    return fa[x];
}
int main(){
    int N , M;
    while(scanf("%d",&N) != EOF){
        if (N == 0) break;
        scanf("%d",&M);
        for (int i = 1; i <= N; i++) fa[i] = i;
        int sum = 0;
        for (int i = 0; i < M; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            int fx = find(x);
            int fy = find(y);
            if (fx != fy) {
                fa[fx] = fy;
                sum++;
            }
        }
        printf("%d\n", N - sum - 1);
    }
    return 0;
}

创作不易,点个赞吧~点赞收藏不迷路,感兴趣的宝子们欢迎关注该专栏~

勤奋努力的宝子们,学习辛苦了!宝子们可以收藏起来慢慢学哦~🌷🌷🌷休息下,我们下部分再见👋( •̀ ω •́ )✧~

相关推荐
爱吃西瓜的小菜鸡4 分钟前
【C语言】矩阵乘法
c语言·学习·算法
志-AOX14 分钟前
C语言入门指南:从零开始的编程之路
经验分享
WANGWUSAN6622 分钟前
Python高频写法总结!
java·linux·开发语言·数据库·经验分享·python·编程
西洼工作室37 分钟前
【java 正则表达式 笔记】
java·笔记·正则表达式
染指11101 小时前
50.第二阶段x86游戏实战2-lua获取本地寻路,跨地图寻路和获取当前地图id
c++·windows·lua·游戏安全·反游戏外挂·游戏逆向·luastudio
初学者7.1 小时前
Webpack学习笔记(2)
笔记·学习·webpack
sjsjs111 小时前
【多维DP】力扣3122. 使矩阵满足条件的最少操作次数
算法·leetcode·矩阵
哲学之窗1 小时前
齐次矩阵包含平移和旋转
线性代数·算法·矩阵
Code out the future1 小时前
【C++——临时对象,const T&】
开发语言·c++
Sudo_Wang2 小时前
力扣150题
算法·leetcode·职场和发展