链式前向星
链式前向星
有段时间没写图论了,准备敲一个前向星结果发现忘了....就挺尴尬的。
简单写一下吧。
前向星在逻辑上是和邻接表是一样的。
用一条链表记录每一个点的邻边就是邻接表。而链式前向星就是两个数组来把所有的边存下来。理论上这两种是一样的,但是用链表会多一个指针,而用vector也会让空间翻倍(容器的性质)。所以作为图论选手学会使用链式前向星是非常必要的。
在使用邻接表的时候我们都知道,一个点对应一条链表,虽然我们在储存空间上有着前后的顺序,但是链表上的每一条边之间实际上是没有逻辑关系的。而前向星就是让链表上的每一条边具有逻辑关系。即前后关系,我们用这个关系来建立链表,这样我们只需要知道一个点的第一条边就可以知道这个点的所有邻边,因为现在它是具有逻辑顺序的。
对于一个点,我们也需要一条链表,在之前的分析中我们就说到知道一个点的第一条边就可以知道链表所有的边,所以我们用一个head[i]储存i的第一条边。在储存的时候我们用一个nxt记录一条边的下一条边,这就是我们之前说的逻辑关系。
但是怎么样储存第一条边,并且记录下一条边呢?
我们可以把每一条边都上一个编号,编号就是它出现的顺序。用cnt记录。
int cnt = 0;
struct Edge{
int to,w,nxt;//to表示终点,w是权值,nxt是下一条边的标号
}edge[N];
int head[N];//记录第一条边(也有的博客说是最后一条边,这是因为前向星是使用的头插法在最前面的就是最后插入的边)
void add(int u,int v,int w){//加边方式
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].nxt = head[u];
head[u] = cnt++;
}
遍历方式:
对于一点如何遍历所有的边呢?
for(int i = head[u]; ~i ; i = edge[i].next)
一行即可