浅谈图的储存方式

  • 建图
    • 邻接矩阵
    • 图的遍历
    • 链式向前星

大家好,我是 ztr,这次我们来浅谈图的储存和遍历。

图的主流储存有一下几种:

方式优点缺点
邻接矩阵编写方便很容易 MLE
邻接表遍历方便
链式向前星内存使用量小编写复杂

综上所说,我还是推荐大家用邻接表,除非在特别卡空间的题目才用链式前向星。

邻接矩阵

顾名思义,邻接矩阵就是一个矩阵 ( ̄▽ ̄)*

这个邻接矩阵的矩阵 a i , j a_{i, j} ai,j 表示 i → j i \to j ij 这条边的权值,如果边不存在,则为 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_backvector 里面,从而节省很多空间。

继续看一道题:


输入一个有向图(结点数小于 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 换成链表,具体代码就不在这里展示了,有兴趣的同学可以看这个

好啦,这一期就到这里,下期会讲最短路的算法,谢谢大家的收看,再见!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值