边集数组

边集数组是由两个一维数组构成。

一个是存储顶点的信息,另一个是存储边的信息。边数组每个数据元素由一条边的起点下标 (begin), 终点下标 (end) 和权 (weight) 组成。

边集数组关注的是边的集合,对顶点的处理效率较低,例如查找某顶点的度,就需要扫描整个边数组。

链式前向星

链式前向星可用于存储图,本质上是一个静态链表,用边集数组和邻接表相结合,可用快速访问一个顶点所有邻接点。

链式前向星存储包括两种结构:

  • 边数组:edge[] ,edge[i] 表示第 i 条边。

  • 头结点数组:head[],head[i] 存以 i 为起点的最后一条边的下标(在edge[]中的下标)。

**链式前向星本质上还是邻接表。**

使用链式前向星,储存 N 个顶点的有向有权图,边集数组对应的边数 M 未指定的情况下,要设置比 NN 大的数(无向图需要再 2 )。

头结点数组 head[a]=i,表示顶点 a 的最后一个邻接边是 edge[i]。

链式前向星的特性:

  1. 和邻接表一样,因为采用头插法进行链接,所以边输入顺序不同,创建的链式前向星也不同。

  2. 对于无向图,每输入一条边,需要添加两条边,互为反向边。例如,输入第一条边 1 2 5,实际上添加了两条边,如图所示:

​ 如果一条边的下标为 i,则其反向边为 i^1 。

  1. 链式前向星具有边集数组和邻接表的功能,属于静态链表,不需要频繁地创建结点,应用十分灵活。
struct Edge{
    int to, w, next;
}edge[M];

int h[N];
int cnt = 0;

void add(int a, int b, int c){
    edge[cnt].to = b;
    edge[cnt].w = c;
    edge[cnt].next = h[a];
    h[a] = cnt++;
}

memset(h, -1, sizeof h);

for(int i = h[x]; ~i; i = edge[i].next){
    int to = edge[i].to;
}

无向图判断是否有环:深搜

除了“父顶点”,邻接点中有标记过的顶点就是有环。

例:

从顶点1开始深搜,访问2,访问3,

访问4时,4的“父顶点”是3,除了3外,1是已经访问过的顶点,所以存在环。

image-20240319235026113

有向图判断是否有环:深搜 + 3色标记

每个顶点有3种标记

  • 0:该顶点未访问过

  • -1:该顶点的邻接点未访问完

  • 1:该顶点的邻接点已访问完

深度优先遍历有向图,如果一个顶点的邻接点有标记为-1的顶点,那么该图中存在环。

如图所示,是一个有向无环图:

如图所示,是一个有向有环图:

假定我们从结点1出发,先访问2这边的边,一直到结点6,这个时候按照深度优先遍历是首先一步步递归进去到结点6。因为结点6没有别的出边,所以就要一步步的按照前面的过程返回。

具体过程:结点1被标记为-1,继续深搜遍历结点2、结点6,然后返回。

在前面2,6结点都返回后,这个时候就算后面的结点比如5访问到6了,它们是不构成环的。

具体过程:结点1还是被标记为-1,继续深搜遍历结点3、结点4、结点5、结点6,然后返回,当结点1已经没有其他邻接点了,就可以标记为1。

当前状态:访问到结点4,被标记为-1,深搜遍历结点5、结点7、结点8。

此时,结点4还是标记为-1,而结点8的下一个点就是结点4,构成环。

results matching ""

    No results matching ""