代码随想录|图论|01图论基础
比较详细的简介看下面这个链接:
图论理论基础 | 代码随想录
这里详细说几个自己不熟的结构:
度的概念
无向图:几条边连接这个节点,这个节点的度就是多少。
有向图:根据连接这个节点的线,指向箭头的是入度,指出箭头的是出度。
有向图是拓扑排序的基本。
连通图
是不是连通图就是任意两个节点是不是可以连起来的,有向图的话需要双向彼此都可以到达。
怎么构造图?
邻接矩阵和邻接表
1、邻接矩阵
用二维数组来表示图结构,从节点的角度出发。
比如grid[2][5] = 6,表示2指向5,权值为6;
比如grid[2][5] = 6,grid[5][2] = 6,表示无向图,权值为6;
一般有n的节点的情况下,需要设置一个 n+1*n+1 大小的邻接矩阵matrix,因为直接用节点数字表示索引比较方便。
这种表达方式在节点多、边少的情况下,会申请过大的二维数组,造成空间浪费,所以说适合稠密图,不适合稀疏图。
2、邻接表
邻接表是“数组+链表”的形式,从边出发,对于每个节点来说,有多少条边,就申请多长的链表。
如下图所示,5个节点,每个节点指向的边构成一个链表。
这里表达的图是:
- 节点1 指向 节点3 和 节点5
- 节点2 指向 节点4、节点3、节点5
- 节点3 指向 节点4
- 节点4指向节点1
下面通过一道题,来用ACM格式创建邻接矩阵和邻接表。
/*
通过邻接矩阵和邻接表两种方式构建有向图。
判断这两图是否完全相同,即每个顶点的邻居集合是否一致。
思路:
1、把邻接矩阵A转换成邻接表A
2、读入邻接表B
3、把邻接表A,B的每个节点的每个邻接表进行排序,方便等会比较
4、依次比较A,B的每个节点的邻接表
*/#include <bits/stdc++.h>
using namespace std;int main()
{int n;cin >> n;// 虽然邻接表是链表,可以用vector<list<int>>表示,但是这里写成二维矩阵是为了操作方便,用push_back末尾添加元素vector<vector<int>> adjA(n + 1);vector<vector<int>> adjB(n + 1);// 根据A的邻接矩阵输入,构建邻接表Afor (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){int val;cin >> val;if (val == 1)adjA[i].push_back(j); // 这里j代表节点}}// 读取邻接表Bfor (int i = 0; i < n; i++){int node, k;cin >> node >> k;// k只是数量,用来控制for循环for (int j = 0; j < k; j++){int val;cin >> val;adjB[node].push_back(val); // 这里node表示起点节点,val代表终点节点}}// 现在两个邻接表的行是按照1~n的顺序排布的,所以对每一行内部进行排序for (int i = 1; i <= n; i++){sort(adjA[i].begin(), adjA[i].end());sort(adjB[i].begin(), adjB[i].end());}// 比较邻接表,逐行比较,他们应该是每一行都相等bool isSame = true;for (int i = 0; i <= n; i++){if (adjA[i] != adjB[i]){isSame = false;break;}}cout << (isSame ? "YES" : "NO") << endl;return 0;
}