struct Edge {
int to, w, next;// to:边的终点 w:边的权值 next:链表的下一条边
}edges[MAXM];
int head[MAXN], cnt; // cnt为当前边的编号
void add(int from, int to, int w) {
++cnt;//拿出一个元素用于存储
edges[cnt].w = w; //边权为w
edges[cnt].to = to; //该边的终点为to
edges[cnt].next = head[from];//当前边作为以from开头的链表的第一条边
head[from]=cnt;
}
思想具体是:我们开设一个足够大的用于存边的内存池,每次需要存边时从内存池中拿出一个元素用来存储(对应了++cnt)。用head[i]表示以i为出发点的可到达的边集中的第一条边,现在我们假设存储一条从from 到 to 的 权值为w的边,具体步骤如下:
1.从内存池中拿出一个元素用于存储 ++cnt
2.设置边权和到达节点:edges[cnt].w=w;edges[cnt].to=to;
3.将新增的边链接到from对应的链表的头上去,和链表的头插法类似 edges[cnt].next=head[from];head[from]=cnt;
当然不要忘记最重要的初始化是让所有的head[i]都预先指向-1。
用图做例子解释一下:
此时如果要插入一条 从5到3的权值为10的边:
此时插入一条1到5的权值为3的边:
对于所有与i建立连接的点的遍历方式为:
for(j=head[i];~j;j=edge[j].next){
//遍历时需要的操作
};
由于我们设置-1为链表的结尾,所有初始化时我们可以借助memset快速赋值,另外,由于-1的补码的二进制全为1,全取反为0,可以跳出循环【位运算效率高】。