图论入门、图的dfs、bfs模板

本文适用于对图论代码实现不了解的初学者。

图的概念

所谓图,即一些顶点和边的集合。其中点的位置、边的形状是无所谓的,重点研究的是点和边的关系。
在图中,一条边仅能连接2个点。边分为有向边(单向连接)和无向边(双向连接)
有向图:边为有向边的图。
无向图:边为无向边的图。
树:边数=顶点数-1的无向连通图。

图的建立

图有两种表示方法:邻接矩阵和邻接表。

邻接矩阵指:对于一个n个顶点的图,建立一个n*n的二维矩阵g[n][n],其中g[i][j]可以按照自己的选择定义:对于无权图,1代表i到j有一条有向边,0代表i到j没有边。对于带权图,a[i][j]=x代表i到j有一条权值为x的边。
如果是无向图,可以让a[i][j]=a[j][i]=x代表i和j连接了一条权值为x的边。
邻接矩阵存在一些缺陷:第一是如果是稀疏矩阵(边数远小于点数的平方),会存在大量的0,浪费了大量的空间,如果n较大时,二维矩阵就无法存储。第二是如果有重边的话(如i到j有两条不同的有向边相连),邻接矩阵将无法存储。

这里介绍一下邻接表。所谓邻接表,指对于n个顶点,先设置n条空链表,假设引进了i到j的一条边,那么在第i个链表上新增一个节点来描述这条边的信息。由于链表占据的空间是可变的,因此这种存图的方法方便存储稀疏矩阵(尤其是树的建立)。

使用vector数组或ArrayList数组建立邻接表

c++里stl标准库的vector工具、java里util包中的ArrayList都是可变长度的数组,可以用来建立邻接表。

vector的说明

需要#include头文件。
vectora; //vector的声明。等价于int a[n]
a.size() //表示a中的元素个数
a.push_back(i) //在a的最后一个元素后面增加新元素i
a.pop_back() //删除a的最后一个元素
a[i] //表示a的第i个元素。a的所有元素是从a[0] 到a[a.size()-1],这一点和数组是一样的。

ArrayList的说明

需要import java.util.ArrayList;导入相关包。
ArrayListlist=new ArrayList(100010); //实例化
list.size() //list中的元素个数。
list.add(x) //最后一个元素之后添加新元素x
list.get(i) //获取第i个元素,所有元素下标是从0到list.size()-1

用vector建立邻接表的示例

输入:
第一行两个正整数n和m,代表顶点数和边数。
接下来的m行,每行两个正整数x和y,代表x到y之间有一条无向边。
样例输入:
3 2
1 2
1 3

vectorg[100010]		//建议使用全局变量。
int n,m;
int main(){
 	cin>>n>>m;
 	while(m--){ 
 		int x,y;
 		cin>>x>>y;
 		g[x].push_back(y);
 		g[y].push_back(x);	//如果是x到y的有向边,则不要这句。
 	}
}

图的dfs模板

int visited[100010];		//全局变量,标记数组。
void dfs(int x){
 	int i;
 	for(i=0;i

图的bfs模板

int visited[100010];		//全局变量,标记数组。
void bfs(){
 	queueq;		//使用队列辅助bfs。
 	q.push(1); 
 	visited[1]=1;
 	while(!q.empty()){
 		int temp=q.front();
 		for(int i=0;i

你可能感兴趣的:(知识点)