存储图可以用邻接表和邻接矩阵
以下代码来自 https://www.acwing.com/blog/content/405/
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx, w[N];
// 添加一条边a->b,权重是w
void add(int a, int b, int w)
{
e[idx] = b, ne[idx] = h[a], w[idx] = w, h[a] = idx ++ ;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);
解释:
虽然是链表,但是没有用指针实现。实际上每条边都有一个编号(也就是idx
),用编号来定位一条边,指向下一条边。
一个邻接表需要两种数据,一个是头结点,一种是边结点。头结点a
指向边结点b
,表示一条边a --> b
。
在这里头结点的结构是一个数组:i
表示某点;h[i]
是从i
出发的一条边的编号,也就是指向了这条边。
边结点的结构:j
表示某条边的编号;e[j]
是这条边的终点;w[j]
是这条边的权重;ne[j]
是该结点指向的下一条边的编号。
idx是边的编号,和头结点一点关系都没有。
下面解释add
函数的内容。这里使用的是头插法(实际上也不好用尾插法):
//插入一条a->b,权重为w的边
//处理边节点
e[idx] = b,w[idx] = w; //初始化边结点的终点和权重
ne[idx] = h[a]; //让新的边结点的next也指向h[a]指向的那条边
//处理头结点
h[a] = idx ++ ; //让头结点指向新的边