------------------------------施工中---------------------------

前置知识:递归、DFS、BFS、回溯、栈、队列、树、基础动态规划、链表

(下文中,n 表示图中点的个数,m 表示图中边的个数)

 

一、图的存储

  1、邻接矩阵:

    用二维矩阵 {ai,j}(n*n) 表示点 i 与点 j 之间是否有边直接相连以及边的状态。

 

  2、边表:

    存储图中的所有边,示例代码中 x 和 y 为边的两个端点,v 为边的状态。

1 struct edge {
2     int x, y, v;
3 } edge[MAX + 10];

 

  邻接矩阵与边表的对比:

    邻接矩阵以矩阵的方式将图存储了起来,显然空间复杂度为 O(n2),边表则仅存储图中边的信息,显然空间复杂度为 O(m),因而稀疏图中,边表存储效率更高,稠密图中二者相差不大

    1)对于询问图中某两点之间是否有边直接相连,邻接矩阵可以直接检查 ai,j 的具体值,边表则需进行遍历。

      显然,邻接矩阵的效率更高

    2)对于查找所有与 i 直接相连的点,可以检查 ai,j(j ∈ [1, n],j ≠ 0) 的值,时间复杂度为 O(n),边表仍需遍历,时间复杂度为 O(m)

      一般情况下邻接矩阵的效率更高。

      为了提高这类问题下边表的效率,将边表中的边改为单向边,引入前向星和邻接表。

 

  3、前向星:

    对于边集 E,获取其对应单向边表(x 为起点(第一关键字),y 为终点(第二关键字)),将边表按照第一关键字进行排序,对于某一点 i ,记录其在排序后的边表中,以该点为起点的边所在的边表下标区间 [l, r]。

    显然,如果要查找所有与 i 直接相连的点,仅需从 l 遍历至 r 即可。

 1 int l[MAXN + 10], r[MAXN + 10];
 2 struct Edge {
 3     int x, y;
 4     friend bool operator < (const Edge a, const Edge b);
 5 } edge_list[MAXM + 10];
 6 
 7 bool operator < (const Edge a, const Edge b) {
 8     return a.x < b.x;
 9 }
10 
11 void prepare() {
12     std::sort(edge_list + 1, edge_list + 1 + m * 2);
13     l[edge_list[1].x] = 1; r[edge_list[m * 2].x] = m * 2;
14     for (int i = 2; i <= m * 2; ++i) if (edge_list[i].x != edge_list[i - 1].x) {
15         r[edge_list[i - 1].x] = i - 1;
16         l[edge_list[i].x] = i;
17     }
18 }
前向星

相关文章: