个人见解,如有错误,欢迎指出。
作为一个算法新手,我就从我个人的角度来讲述前向星这种算法,我看到大多数都是建立一个边集的结构体,然后在结构体内放入边指向结点,边的前驱,和边权:
例如:
struct edge{//建立一个边集结构体 int next;//好一点的把next换成了pre,从字面上来讲更好理解 int w;//边的权值 int v;//边指向结点,有的写成to }e[maxn];
当然对于一个已经懂得了前向星的人来讲,这种写法也还是比较好理解的。下面进入主题:
同样的我们还是建立一个结构体,但是,我们把名字改成graph,没错,就是graph。表明我们是对一个图进行操作。
由于前向星是一种反向遍历的方式,我们把相应的next和v改成front和to,这样从字面生更好理解。我们按输入顺序对每条边赋予一个值,表明是第几条输入边(也就是说每条边都有一个独一无二的IP地址了)
即:使用链表方式存储图的边。last[i]用来记录以i为起点且为最后输入的一条边,front[j] 表示边j的前一条边(这里的前一条边不仅仅是指输入顺序在j的前面,而且还得和j拥
有相同的起点),to[j]表示第j条边所指向的结点编号。即:令addr=last[i],之后不断用 addr=front[addr]即可得到链表中所有以结点i为起点的所有“边集的编号”,其中
to[addr]表示对应边指向的结点编号。那么这样做有什么用呢?比如我们想知道有没有一条从u到v的边,我们只需要这样遍历所有从u出发的边,看有无终点是v即可。
代码:
struct graph{ int last[maxn],front[maxn],to[maxn],w[maxn],cnt; void init(){//初始化 memset(front,-1,sizeof(front));//-1表示某条边不存在前驱边 memset(to,0,sizeof(to)); memset(last,0,sizeof(last)); cnt=0; } void add(int u,int v,int W){ cnt++;//使边的编号从1开始 to[cnt]=v;//记录该边的指向结点 w[cnt]=W;//记录该边的权值 front[cnt]=last[u];//用尾插法把该边放入以u为起点的边集中 last[u]=cnt;//更新以u为起点且为最后输入的边 //如果是无向图,加入下面这句话 /* swap(u,v); cnt++; to[cnt]=v; w[cnt]=W; front[cnt]=last[u]; last[u]=cnt; */ } }G;
好了我的讲述就到这里了吧,个人认为这种写法还是比较好理解的,代码嘛也不是很长。
时间: 2024-10-09 05:42:04