图的储存
图的建立有两个问题要解决。
- 用什么数据结构存储 (邻接表和邻接矩阵)
- 图有有两种类型。有向图和无向图应该如何表示。 (无向图表示,两点互相有边指向,这样可以统一都用有向图的方式来储存)
储存结构
如果有n个点,m条边的图。他们可以用邻接表和邻接矩阵表示。
邻接矩阵
g[a][b] 存储边a->b
- 时间复杂度O(n^2)
邻接表(用数组来模拟链表)
其实和链式前向星是一回事,如果不明白。可以去看看那个笔记的图。
- 用数组来模拟链表
- head[i]表示以i为起点的头节点。也就是第一条边的序号
- head数据,每个利用头插
- e[i], ne[i], idx;
- e[i] 代表边i 指向的节点的序号
- ne[i] 代表边i 一条“兄弟边”的序号
- idx 记录边的序号,从0开始
邻接表的代码
//邻接表,表示图
//
#include <bits/stdc++.h>
const int N = 1e5 + 10;
const int M = 1e5+10;
using namespace std;
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N],e[N],ne[M],idx;
// 添加一条边a->b
void add(int a, int b){
//线的序号从0开始
e[idx] = b, ne[idx] = h[a], h[a] = idx++;//头插
}
//遍历以a为首的直接边
void print(int a ){
for (int i = h[a]; i != -1 ; i = ne[i]) {
cout << a << "" << i << endl;
}
}
int n,m;//n个点,m个边
int main(){
//h初始化为-1
memset(h,-1,sizeof h);
cin >> n >> m;
//加边操作
while (m --){
int a, b;
cin >> a >> b;
add(a,b);
}
//遍历以a为首的直接边
print(1);
return 0;
}