图论 __ 链式前向星
概括
以同起点为一条链,数组head[a]存储起点a的最新录入的一条边的索引,每条边以结构体的形式存储该边信息(该边终点,权值,同起点的边中的上一条边即上一次录入的边的位置),所有边构成一个结构体数组。
很多帖子说到的是存储的是下一条边,这种理解很容易给人误导,应该是每一条边都能通过自身结构体存储的信息回溯到上一条边,所以叫前向星。
假如我们要找出一条a -> b的边,先根据head[a]找出从起点a出发的所有边里最新录入的那条边,然后根据该边找出它的上一条边,再根据上一条边找出它的上上一条边……直到找到一条终点为b的边为止。整个过程是链式回溯的,所以是链式前向星。
看完一脸懵? 没关系,直接看下面示范即可
范例
边的录入顺序(起点a -> 终点b = 权值w):
第0条边:5 -> 3 = 1 此时head[5]=0 以5为起点没有上一条边
第1条边:1 -> 2 = 9 此时head[1]=1 以1为起点没有上一条边
第2条边:3 -> 5 = 11 此时head[3]=2 以3为起点没有上一条边
第3条边:2 -> 1 = 5 此时head[2]=3 以2为起点没有上一条边
第4条边:4 -> 5 = 6 此时head[4]=4 以4为起点没有上一条边
第5条边:3 -> 1 = 7 此时head[3]=5 以3为起点的上一条边的是第2条边
第6条边:3 -> 4 = 4 此时head[3]=6 以3为起点的上一条边的是第5条边
第7条边:4 -> 1 = 2 此时head[4]=7 以4为起点的上一条边的是第4条边
假如我们要找3 -> 5这条边:
根据head[3]=6,得到起点3的最新一条录入的边是第6条边
根据edge[6].to=4,这条是3 -> 4的边,不符合,我们继续找
根据edge[6].pre=5,得到第6条边的上一条同起点边是第5条边
根据edge[5].to=1,这条是3 -> 1的边,不符合,我们继续找
根据edge[5].pre=2,得到第5条边的上一条同起点边是第2条边
根据edge[2].to=5,这条是3 -> 5的边,找到了
代码实现
边的结构体
存储该边信息
struct Edge{ int to;//表示该边的终点 int pre;//同起点的上一条边的位置,值为-1表示没有上一条边 int w;//该边权值 }; //定义结构体数组edge,存储每一次录入的边 Edge edge[2*m+2];
定义链头head
存储每个起点的最新一条边的索引,-1表示该点无边
int head[n+1]; memset(head,-1,sizeof(head));
定义一个边的计数器
,表示当前已录入边的数量
int ecnt=0;
增边函数
增加一条a -> b的权值为w的边。
inline void addEdge(int a,int b,int w,int head[],Edge edge[],int &ecnt){ edge[ecnt].w=w; edge[ecnt].to=b; edge[ecnt].pre=head[a];//该边上浮为起点a的所有边里最新的边 head[a]=ecnt++; }
增边函数,只能是有向边,对于无向边再增加一次反向边即可。
addEdge(a,b,w,head,edge,ecnt); addEdge(b,a,w,head,edge,ecnt);
模板代码
int h[N], to[N], pre[M], idx; void add(int a, int b) { to[idx] = b, pre[idx] = h[a], h[a] = idx++; } signed main() { memset(head, -1, sizeof(head)); return 0; }
本文作者:kingwzun
本文链接:https://www.cnblogs.com/kingwz/p/16473160.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步