约定 n 为点数, m为边数,times = [[2,1,1],[2,3,1],[3,4,1]] 表示3条边
2->1 权重为1
2->3 权重为1
3->4 权重为1
1.邻接矩阵
这是一种使用二维矩阵来进行存图的方式。
适于边数较多的「稠密图」使用,当边数量接近点的数量的平方,即m≈n²时,可定义为「稠密图」。
| 12
 3
 4
 5
 6
 7
 
 | int[][] w = new int[N][N];
 
 
 void add(int a, int b, int c) {
 w[a][b] = c;
 }
 
 | 
2.邻接表(链式前向星存图)
适用于边数较少的「稀疏图」使用,当边数量接近点的数量,即m≈n 时,可定义为「稀疏图」。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | int[] he = new int[N], e = new int[M], ne = new int[M], w = new int[M];int idx;
 
 void add(int a, int b, int c) {
 e[idx] = b;
 ne[idx] = he[a];
 he[a] = idx;
 w[idx] = c;
 idx++;
 }
 
 | 
首先 idx 是用来对边进行编号的:
1.he 数组:存储是某个节点所对应的边的集合(链表)的头结点;
如下图所示:he[u]=边4
注意:仅仅是存储头结点,之后就可以根据ne数组进行查找!

2.e 数组:某一条边指向的节点:e[边4]=v4
3.ne 数组:由于是以链表的形式进行存边,该数组用于找到下一条边
ne[边4]=边3;构建链表的过程是头插法:null<-边1<-边2…
4.w 数组:用于记录某条边的权重为多少。
编码的边是用idx作为索引来进行标记的,也就是说每一个idx对应一条边
因此当我们想要遍历所有由 a 点发出的边(注意是a伸出的边) 时,可使用如下方式:
| 12
 3
 4
 
 | for (int i = he[a]; i != -1; i = ne[i]) {
 int b = e[i], c = w[i];
 }
 
 | 
3.类
这是一种最简单,但是相比上述两种存图方式,使用得较少的存图方式。
只有当我们需要确保某个操作复杂度严格为O(m) 时,才会考虑使用。
具体的,我们建立一个类来记录有向边信息:
| 12
 3
 4
 5
 6
 7
 
 | class Edge {
 int a, b, c;
 Edge(int _a, int _b, int _c) {
 a = _a; b = _b; c = _c;
 }
 }
 
 | 
通常我们会使用 List 存起所有的边对象,并在需要遍历所有边的时候,进行遍历:
| 12
 3
 4
 5
 
 | List<Edge> es = new ArrayList<>();...
 for (Edge e : es) {
 ...
 }
 
 | 
4.HashMap
注意:如果节点索引集中可以用List数组代替HashMap,具体参考List数组创建与初始化方法
key为出发点,value为该出发点对应的终点列表(一个出发点可能对应多个终点)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 
 | HashMap<Integer, List<Integer>> map = new HashMap<>();
 for (int[] edge : edges) {
 List<Integer> list1 = map.getOrDefault(edge[0], new ArrayList<>());
 list1.add(edge[1]);
 map.put(edge[0], list1);
 
 List<Integer> list2 = map.getOrDefault(edge[1], new ArrayList<>());
 list2.add(edge[0]);
 map.put(edge[1], list2);
 }
 
 
 HashMap<Integer, List<int[]]>> map = new HashMap<>();
 for (int[] edge : edges) {
 List<int[]> list1 = map.getOrDefault(edge[0], new ArrayList<>());
 list1.add(new int[] {edge[1], edge[2]});
 map.put(edge[0], list1);
 
 List<Integer> list2 = map.getOrDefault(edge[1], new ArrayList<>());
 list2.add(new int[] {edge[0], edge[2]});
 map.put(edge[1], list2);
 }
 
 
 
 List<Integer>[] list = new List[n];
 
 for (int i = 0; i < n; i++) list[i] = new ArrayList<>();
 for (int[] e : edges) {
 
 list[e[0]].add(e[1]);
 
 list[e[1]].add(e[0]);
 }
 
 |