图的深度、广度优先遍历讲义

1.基本概念

图可以理解成一个二元组,是由点集\(V\)和边集\(E\)组成的。
\(G=(V, E)\)\(V\)表示点的集合,\(E\)表示边的集合。
每条边是一幅点对\((v,w) v,w\)都是点集V中的点。\((v,w∈V)\)

图的分类:可以按照边有无方向,可以分为有向图和无向图。

无向图:每条边都是无向的图为无向图

有向图:每条边都是有向的图为有向图

图的分类:可以按照边的数量分为,简单图和多重图

简单图:在无向图中,任意2点间只有1条边;在有向图中,任意2点间只有1条同向边

多重图:在无向图中,任意2点间不只有1条边;在有向图中,任意2点间不只有有1条同向边

图的度

在无向图中,与这个结点相连的边的个数,称为结点的度。比如在图1中,\(X\)的度数为4
在有向图中,结点的度分为入度和出度。
结点的入度:以这个结点为终点的有向边的个数
结点的出度:以这个结点为起点的有向边的个数
比如在图2中,\(A\)的入度为0,出度为2
性质:\(图的总度数=边数*2\)

连通

无向图中:从任意点,都存在到达其它点的路径,称为连通图。
有向图中:从任意点,都存在到达其它点的路径,称该有向图是强连通的 。

子图

对于图\(G\)和图\(G’\),如果图\(G’\) 的边集和点集都是图\(G\)的边集和点集的子集,那么图\(G’\)是图\(G\)的子图

导出子图

对于图\(G\)和图\(G’\),如果图\(G’\)的点集都是图\(G\)点集的子集,那么图\(G’\)是图\(G\)的导出子图,其边集不一定是图\(G\)边集的子集。

补图

对于图\(G\)和图\(G’\),如果\(2\)个图的点集相同,边集没有交集,并且边集为完全图的边集,那么图\(G\)和图\(G’\) 互为补集。

其它概念

权值: 边的“费用”,可以看成是边的长度

回路: 起点和终点相同的路径,称为“回路”,或者“环”

完全图: 无向图中,如果任意两点之间都存在一条边,则是一个无向完全图,无向完全图有\(n*(n-1)/2\)条边;有向图中,如果任意两点之间都存在互通的两条边,则是一个有向完全图,有向完全图有\(n*(n-1)\)条边。

稠密图: 边数接近于完全图的图

稀疏图: 边数远远少于完全图的图

强连通分量: 有向图中任意两点都连通的最大子图。

2. 图的存储方式–邻接矩阵

int G[i][j]; //G[i][j]表示从点i到点j的权值,定义如下
G[i][j] 有边 没有边
有权图 权值
无权图 1 0

3. 图的存储方式–邻接表

邻接矩阵存储的缺点在于,当图是稀疏图时,邻接矩阵的存储效率很低。为此,我们图有另外一种存储方式,邻接表。

无权图的邻接表存储

顶点 相邻的顶点的列表
0 1
1 3
2 1
3 0,2
4 3
vector<int> g[MAXN];
g[i].push_back(j);//i→j 存在有向边
//g[j].push_back(i); 如果是无向图,该代码也得加上。
#include <vector>
vector<int> G[5];
G[0].push_back(1);
G[1].push_back(3);
G[2].push_back(1);
G[3].push_back(0);
G[3].push_back(2);
G[4].push_back(3);

有权图的邻接表存储
因为除了需要存放点集之外,也要存放权值,此时定义结构体

struct edge{
  int to;
  int w;
}
vector<edge> g[MAXN];

g[i].push_back((edge){j,w});//i→j 存在有向边,权值为w
g[j].push_back((edge){i,w});//如果是无向图,该代码也得加上。

4. 图的深搜

邻接矩阵存储时,时间复杂度O(n^2),邻接表存储时,时间复杂度是O(n+m)

bool vis[MAXN];
bool G[MAXN][MAXN];
void dfs(int pos){
	vis[pos]=true;
	for(int i=1;i<=n;i++){
		if(!G[pos][i]) continue;
		if(vis[i]) continue;
		dfs(i);
	}
}

5. 图的广搜

邻接矩阵存储时,时间复杂度O(n^2),邻接表存储时,时间复杂度是O(n+m)

for(int pos=1;pos<=n;pos++){
	if(vis[pos]) continue;
	q.push(pos);
	vis[pos]=true;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=0;i<g[u].size();i++){
			int v=g[u][i];
			if(!vis[v]) continue;
			vis[v]=true;
			q.push(v);
		}
	}
} 
posted @ 2021-05-28 22:52  ICtiger  阅读(242)  评论(0)    收藏  举报