链式向前星知识点&代码
Posted dudujerry
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链式向前星知识点&代码相关的知识,希望对你有一定的参考价值。
代码:
struct NODE{ int to; int nxt; int c; }node[MM];//链式向前星 int head[NM],lcnt=1; void add(int a,int b,int c){ node[lcnt].to=b; node[lcnt].c=c; node[lcnt].nxt=head[a]; head[a]=lcnt++; }
1.使用结构体构建链式向前星的容器
链式向前星本质上是使用链表存边,一条链表代表着一个点发出的所有边。所以一个这个结构体代表着这条链表中的一项
struct NODE{ int to; //指向下一条边 int nxt; //指向同一个点发出的另一条边 int c; //边权 }node[MM];//链式向前星
2.第一条边——head和边的编号
NM是一个常量,代表着点的数量;
head代表着一条链表的第一个项,也就是一个点所发出的第一条边(第一的意思是可以从这链表的这一项一直跳完所有项),至于如何实现请看 3 部分。
lcnt是赋予边编号的变量,之所以初始化为1,请看 4 部分。
int head[NM];
int lcnt=1;
3.三个变量一台戏——如何加边(add)
a,b,c分别代表入边,出边,权值
这个函数设置编号为lcnt的边,将to指向的是节点编号
重点在nxt的操作上。将nxt赋值为a节点的“第一条边”,那么就是说这个点接下来的可以跳的边或者说链表的项是 head[a]
接下来将”第一条边”赋值为当前的编号,那么下一次添加以a为源点的边可以跳的边或者说链表的项就是现在的边或者说项了。
那就意味着最后一次添加的边(项),可以一直跳到第一次添加的边(项),也就符合我们在第 2 条定义的“第一条边”了。
别忘了将编号++,以便下次使用。
void add(int a,int b,int c){ //改变编号为lcnt的边 node[lcnt].to=b; //出边指向b node[lcnt].c=c; //记录权值 node[lcnt].nxt=head[a]; //将其指向目前的”第一条边“,也就是说能跳到”第一条边” head[a]=lcnt++; //“第一条边”更新为目前的编号,那么下一条边能够跳到这一条边,那么最后的head自然就是真正的“第一条边”了;编号++一遍下次使用 }
4.遍历某个点所连接的所有边
要遍历就可以利用前面求出的”第一条边“和这些链表了。
自然可以用for,从一开始将循环变量i初始化为要遍历的源点k的”第一条边“,head[k]
在判断的时候,判断是否还有下一条边,这时候就是lcnt初始化为1的作用了。如果没有初始化为1,就会存在编号为0的点,判断就会误认为已经结束了。
于是判断就必须写i!=-1了,但是打"=1"只需要两个字符,而"i!=-1"比起"i"要多4个字符,而且不符合我们人类的思维习惯:从1开始,所以我们采用lcnt初始化为1
(“i”在C++里的意思是简写的 i!=0 )
然后到每次循环结束做的改变,自然是直接跳到链表的下一项。
for(int i=head[k];i;i=node[i].nxt){ int u=node[i].to; //u就是所连接的点
int v=node[i].c;
//v就是边的权值
}
以上是关于链式向前星知识点&代码的主要内容,如果未能解决你的问题,请参考以下文章