图论基础 [从入门到黑题]

前言

楼主打模拟赛自闭就出来写blog了

本编blog目的是写一篇全网最详细的图论从基础到各种算法(在我会的范围,因此目前会不断更新)。

update : 如果这个人没有退役就会把这篇blog更完

Q :什么是图?

A :在计算机科学里,图大概长这个样子(这是一张我随手画的图):

因此,图的非正式定义很简单,就是 有一些结点(node),有一些边(edge)将点连起来

我们可以形象的理解为 有若干个城市,每个城市间有一些道路相连,其中,城市就是结点,道路就是边。图就是整个城市群(这个是最短路里常用的图论模型)


我们发现图就两个东西 :结点,因此可以看见一些学术性的blog或百科里把图抽象成 点集 \(V\) 和 边集 \(E\) (这里是集合知识,不知道不大要紧)。

因此,我们要保存一个图,或获得一个图的信息,就只要知道它的 结点与边 的情况即可。接下来我们从 结点 与 边 角度继续来了解图(下面还是基础知识,只要了解,理解,留下印象

有向图 与 无向图

这里是从边的角度来了解图

Q :什么是有向图无向图

A :这你得知道什么是有向边无向边

Q :那什么是有向边无向边

A :

上图是一条无向边,我们称这是一条由 1 到 2 的无向边,(标了 1 就是编号为 1 的结点)。边的一般形式是 \((u,v)\) , 所以这里就是\((1,2)\)

在无向边里,1可以通向2, 2可以通向1

用城市群这个比喻:我们可以把它看成 城市1 与 城市2 之间有一条道路,这条路是双向公路。这就是无向边的意义。

上图是一条有向边。与上上这条无向边一样,就是多了一个箭头。这个箭头表示 只能由 1 通向 2

我们同样可以把它看成 城市1 与 城市2 之间有一条道路,但是是一条单向公路

所谓 无向图无向边,就是在一张图中的边是无向边还是有向边

  • 无向图中的边就是无向边,每条边的两个端点可以互相到达。相当于城市之间全部是双向公路,汽车可以来回通行

  • 有向图中的边就是有向边,端点只能沿箭头方向走到另一边。相当于城市之间是单向公路,汽车只能沿公路方向通行

(下图是一张经典的有向图)

有向图与无向图一般会由题目给出


小问题:有向图中的两个城市可否互相到达(达到无向图这个效果)?

可以。其实无向图就相当于一种特殊的有向图。就是建了方向相反的两条有向边。

从边的角度浅显的了解了一下图,接下来抽象地来理解一下图

状态与状态间的关系 和 图的联系

之前一直在用城市来理解图,为了能让自己的知识与思维扩展开来,我们要从图的本质上来理解它。

图可以用来表示状态与状态之间的关系

Q :如果来理解 图可以表示状态与状态间的关系?

我们可以把一个状态看成一个结点,如果能从状态\(u\) 通过某些方式达到 状态\(v\) 我们就可以在图上把 \(u->v\) 连一条边。连完边后,整个状态之间就变成一张有向图

(这里要自己联想联想,感悟一下。。。)

这样说太抽象了,我们来看一道例题:

P1135 奇怪的电梯

有n层电梯,每个电梯可以到按按钮通向另一层电梯。问从A电梯到B电梯最少要多少步

(其实是Bfs的模板题) 我们把每个电梯看成一个结点,通向其他电梯就是其他结点,建一条有向边,整个问题就可以抽象成一张图了。

目前为止,我们初步知道了图是什么————表示问题的一种方式;图的样子————结点和边;可以说,我们从理论上理清了图的概念。接下来,我们要把概念用代码实现出来,学习 图的储存

图的储存

图的储存有三种常用的方法,邻接矩阵存图,链式前向星存图,vector存图,其中邻接矩阵存图代码简易但效率低下,前向星和vector效率相当,vector略慢。读者务必掌握前向星,因为掌握了前向星也不难理解其他两种存图,并且本篇blog的代码多用前向星存图。

邻接矩阵存图

我才不会告诉你邻接矩阵就是一个二维数组

给你一张有向图 输入n,m 表示这张图有n个点m条边,之后有m行,每行有两个数 u,v 。请你把这个图保存下来。

(这是一般图论题最前面部分)

const int N = 1007;    //n<=1000
int g[N][N];    //graph 图; 这个二维数组就是邻接矩阵,请看下面
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;++i) {    //输入m条边
        int u,v;
        cin>>u>>v;
        g[u][v] = 1;    //因为开始g[u][v]=0表示u->v没有路径,如果为1则表示有一条边
    }
    return 0;
}

可以看出,邻接矩阵存图的代码浅显易懂。如果 g[u][v]==1 就表示 \(u->v\) 有边。

链式前向星

邻接矩阵的空间大小与点数有关,当结点达到 n=10000 时,它不再适用。因为一般题目中的点很多,但是边往往只有 m<=10 0000,于是算法大神发明了以边数的存图算法————链式前向星

我们来看一张图:

1 点有三条连出的边,(1,2),(1,3),(1,4),我们可以称这是 1点的三条出边。

所谓链式前向星,就是把每个点的出边保存在一起。代码

int cnt,head[N];
struct Edge {
    int next,to;    //next表示链表中下一个元素的下标,to是当前点边指向的点
}edge[M];
全部评论

相关推荐

已老实求offer😫:有点像徐坤(没有冒犯的意思哈)
点赞 评论 收藏
分享
菜菜咪:1. 可以使用简历网站的模版,美观度会更好一点 2. 邮箱可以重新申请一个,或者用qq邮箱的别名,部分hr可能会不喜欢数字邮箱 3. 项目经历最好分点描述,类似的项目很多,可以参考一下别人怎么写的 4. 自我评价可加可不加,技术岗更看重技术。最后,加油,优秀士兵
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务