首先我们来看一下什么式前向星
前向星是一种数组集合,按照起点排序,起点相同再按照到终点的顺序进行排序,我们设两个数组来,一个存放每个点链接了几个点(len[i]),一个记录在数组集合中的第一个起始位置(head[i]);
我们假定一个有向图
我们输入边的顺序为:
1 2
2 3
3 4
1 3
4 1
1 5
4 5
排完序之后则得到:
编号: 1 2 3 4 5 6 7
起点: 1 1 1 2 3 4 4
终点: 2 3 5 3 4 1 5
用数组表示为:
head[1] = 1 len[1] = 3
head[2] = 4 len[2] = 1
head[3] = 5 len[3] = 1
head[4] = 6 len[4] = 2
前向星由于有了排序这一环节,我们的时间复杂度最低多了O(nlogn)
为了解决办法,大犇利用链表的思想,省去了排序,便得到了链式前向星
先建立一个结构体
struct Edge{
int to;
int w;
int next;
};
再建立一个构造链式前向星的函数
void add(int u,int v,int w)
{
edge[cnt].w = w;
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
其中edge[cnt].to表示第i条边的终点,edge[cnt].next表示与第i条边同起点的下一条边的存储位置,edge[cnt].w为边权值.
head[u],它是用来表示以i为起点的第一条边存储的位置,实际上你会发现这里的第一条边存储的位置其实在以i为起点的所有边的最后输入的那个编号.
这里可能有些懵,来看一下具体的实例(还是按上面的例子来说)
cnt的初始值是为0的,head数组的初始值都是为-1的
edge[0].to = 2; edge[0].next = -1; head[1] = 0;
edge[1].to = 3; edge[1].next = -1; head[2] = 1;
edge[2].to = 4; edge[2],next = -1; head[3] = 2;
edge[3].to = 3; edge[3].next = 0; head[1] = 3;
edge[4].to = 1; edge[4].next = -1; head[4] = 4;
edge[5].to = 5; edge[5].next = 3; head[1] = 5;
edge[6].to = 5; edge[6].next = 4; head[4] = 6;
很明显head存的是同一起点编号最大终点的位置,head[1]最后的值将被覆盖为5
例如起点为1,我们最先找到的应该是5,然后是3,最后是0,找到next为-1*即表示找再没有与之相同的起点的边存在,即结束。
我们也可以看出它应该是倒着遍历的
代码表示为
for(int i=head[u];i!=-1;i=Edge[i].next)