一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情。
树与图的存储
树是一种特殊的图,一种无环连通图
图的分类:
- 有向图:边有方向
- 无向图:是一种特殊的有向图,比如a和b之间,可以建两条有向边,一条是a到b,一条b到a的边
有向图的存储
- 邻接矩阵
- 开一个二维数组即可,g[a, b]:存的a->b的一条边
- true:表示这条边存在
- false:表示这条边不存在
- 适合存储:稠密图
- 邻接表
- n个点就开n个单链表
- 每个点的单链表就是存的这个点可以走到哪个点
代码
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010, M = N * 2;
int h[N], e[M], ne[M], idx; // e:存所有的结点的值; ne:存所有结点的next值是多少
// 插入一条a指向b的边,也就是在a对应的邻接表的表头插入b
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int main()
{
memset(h, -1, sizeof h); // 链表的初始化,将所有的头全部初始化为-1即可
}
题目
相关概念
- 重边
- 自环
分析
- 边的长度是1,说明可以用bfs来求最短路
代码
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n, m;
int h[N], e[N], ne[N], idx;
int d[N], q[N]; // d:距离; q:队列
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int bfs()
{
int hh = 0, tt = 0; // 定义队头跟队尾
q[0] = 1; // 第一个元素是1
memset(d, -1, sizeof d); // 初始化距离,-1表示没有遍历过
d[1] = 0; // 第一个点已经被遍历过了,所以更新为0
// bfs框架
while (hh <= tt)
{
int t = q[hh++]; // 取队头元素
// 拓展队头的所有点
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (d[j] == -1) // 说明没有被遍历过的话
{
d[j] = d[t] + 1;
q[++tt] = j; // 放入队列
}
}
}
return d[n];
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
for (int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
add(a, b);
}
cout << bfs() << endl;
return 0;
}