- 建图
- 邻接矩阵
- 图的遍历
- 链式向前星
大家好,我是 ztr,这次我们来浅谈图的储存和遍历。
图的主流储存有一下几种:
方式 | 优点 | 缺点 |
---|---|---|
邻接矩阵 | 编写方便 | 很容易 MLE |
邻接表 | 遍历方便 | … |
链式向前星 | 内存使用量小 | 编写复杂 |
综上所说,我还是推荐大家用邻接表,除非在特别卡空间的题目才用链式前向星。
邻接矩阵
顾名思义,邻接矩阵就是一个矩阵 ( ̄▽ ̄)*
这个邻接矩阵的矩阵
a
i
,
j
a_{i, j}
ai,j 表示
i
→
j
i \to j
i→j 这条边的权值,如果边不存在,则为 INF
,如果
i
=
j
i = j
i=j,为
0
0
0。
现在我们看一道题目:
给定一个有向无环图,输出这个有向无环图的邻接矩阵,注意如果 i = j i = j i=j, a i , j = 0 a_{i, j} = 0 ai,j=0。
第一行 n n n 和 m m m,其中 n n n 为顶点数, m m m 为边数; 第二行到第 m + 1 m + 1 m+1 行,为从顶点 i i i 到顶点 j j j 之间的边, i i i 和 j j j 之间以空格分隔。 输入数据保证没有重边。
数据:
输入数据:
4 5
1 2
1 3
3 4
4 1
2 4
输出数据:
0 1 1 0
0 0 0 1
0 0 0 1
1 0 0 0
这个样例对应的图片:
解题步骤:
首先我们要建图:
int n, m; cin >> n >> m;
for (int i = 1; i <= m; i ++) {
int x, y; cin >> x >> y;
a[x][y] = 1;//建立 x 到 y 的一条边
}
接下来就是输出,直接输出矩阵就行了,完整代码:
#include <bits/stdc++.h>
using namespace std;
int a[10005][2005];
int main() {
int n, m; cin >> n >> m;
for (int i = 1; i <= m; i ++) {
int x, y; cin >> x >> y;
a[x][y] = 1;
}
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) {
cout << a[i][j] << " ";
}
cout << "\n";
}
return 0;
}
然后我们试着提交一下,AC!!
邻接表
邻接表类似邻接矩阵,但是不会花费空间出储存不存在的边。
每个点都会有一个对应的 vector
,这个点的所有能到达的点都会被 push_back
到 vector
里面,从而节省很多空间。
继续看一道题:
输入一个有向图(结点数小于 100000 100000 100000,边数少于 200000 200000 200000)。并打印该有向图的邻接表。
第一行 n n n 和 m m m,其中 n n n 为顶点数, m m m 为边数; 第 2 2 2 行到第 m + 1 m + 1 m+1 行,为从顶点 i i i 到顶点 j j j 之间的边, i i i 和 j j j 之间以空格分隔。 输入保证所有边 ( i , j ) (i,j) (i,j) 的终点 j j j 是单调不降的。输入不保证没有重边。
输出为起点结点编号:所有边终点结点编号。 起点结点编号升序,终点节点编号按降序排列。
这道题的邻接表示意图如下:
首先,我们先读入和建图:
for (int i = 1; i <= m; i ++) {
int x, y; cin >> x >> y;//输入,建立一条从 x 到 y 的边。
w[x].push_back(y);//点 x 多加一条通往 y 的边。
}
接着,输出,AC代码:
#include <bits/stdc++.h>
using namespace std;
vector <int> w[100005];
int main() {
int n, m; cin >> n >> m;
for (int i = 1; i <= m; i ++) {
int x, y; cin >> x >> y;
w[x].push_back(y);
}
for (int i = 1; i <= n; i ++) {
cout << i << ":";
for (int j = w[i].size() - 1; j >= 0; j --) {
cout << w[i][j] << " ";
}
cout << "\n";
}
return 0;
}
链式向前星
这时一个占用空间最小的算法,原理就是把邻接表的 vector
换成链表,具体代码就不在这里展示了,有兴趣的同学可以看这个。
好啦,这一期就到这里,下期会讲最短路的算法,谢谢大家的收看,再见!