我在学习图论的时候学了一种存图的方式,链式前向星,它可以用来存储一些大型图
链式前向星是以边为主的存图方式,所以需要用结构体来实现
首先我们需要先建立一个结构体node和一个数组head
const int maxn = 2e6 + 7;
struct node{
int to; // 这条边到达的另一个点
int val; // 边权
int next; // 当前结点的最后一条边指向的上一条边
}E[maxn];
int head[maxn]; // 指向结点i的最后一条边的编号
先说head数组
这个head数组存储的是当前结点i指向的最后一条边的编号
这么说可能有点难懂
看下面这个图
1这个结点指向3 2 4这三个点
我们假设1 -> 3的这条边为1
1 -> 4 的为2
1 -> 2 的为3
2 -> 3 的为4
2 -> 4 的为5
按顺序来说1指向的最后一条边的编号就是3,那么head[1] = 3
同理head[2] = 5
head数组理解之后再来看这个结构体
我理解的链式前向星的基本思想是顺着增边,倒着遍历
这个顺着增边大家肯定都能理解,就是一条一条的往这个图的结构体里增加边
这里的倒着遍历就用到结构体里的next了,这个next相当于是一个指针,它指向head数组里面最后一条边的上一条边,这样一步步的就可以实现倒着遍历
还是看上面那个图
head[1] = 3 那么 E[1].next = 2
head[2] = 5 那么 E[2].next = 4
弄明白这些变量之后我们就可以开始愉快的存图了
可以定义一个add函数来实现
void add(int u,int v,int w)
{
++cnt; // 编号
// 加入一条边
E[cnt].next = head[u];
// 让当前的next指针指向当前结点u的最后一条边的编号
head[u] = cnt;
// 当前结点的最后一条边的编号就等于新加入的边的编号
E[cnt].to = v;
E[cnt].val = w;
}
整理一下总的代码就是这个样子
// 链式前向星
const int maxn = 2e6 + 7;
int cnt;
struct node{
int to, val, next;
}E[maxn];
int head[maxn];
void add(int u,int v,int w)
{
++cnt; // 编号
// 加入一条边
E[cnt].next = head[u];
head[u] = cnt;
E[cnt].to = v;
E[cnt].val = w;
}
int main(){
int n; cin >> n;
for(int i=1;i<=n;i++){
int u,v,w;
cin >> u >> v >> w;
add(u,v,w);
}
return 0;
}