学完这个东西后,给我的感觉是这就是个静态的邻接表。。。(不知道理解的对不对)
这个可以用于给的图边很少,但是点很多的情况二维数组可能就开不下了。就要用到链式前向星
首先,链式前向星由一个结构体
struct edge
{
int next; //上一条边的的存储下标(因为它遍历的时候是从后往前遍历,可以说是前一条边)
int v; //这一条边的终点
int w; //这一条边的权值
}e[N]; //e[i]表示第i条边
各个值代表的意义已经标注了
还有一个head数组
int head[N]; //head[i]表示以i为起点的最后一条边的编号
加边
void add(int u,int v,int w)
{
e[++tot].next=head[u];
e[tot].v=v;
e[tot].w=w;
head[u]=tot; //把当前新加的边作为第一条边
}
把当前边的next赋给这个点的第一条边,再把这个点的第一条边更新成当前这个边。tot初始为0
这样增加完后,可以发现head[i]为以i为起点的最后输入的那条边的编号。
是不是感觉与数组实现的邻接表类似。。
遍历
for(int i=1;i<=n;i++){
int k=head[i];
while(k!=0){ //这里head数组初始化为0,若边的下标从0开始,就初始化为-1,那么判断就是k!=-1
printf("%d %d %d\n",i,e[k].v,e[k].w);
k=e[k].next;
}
}
完整的代码
#include<bits/stdc++.h>
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e5+10;
int n,m,tot;
struct edge
{
int next; //前一条边的的存储下标
int v; //这一条边的终点
int w; //这一条边的权值
}e[N]; //e[i]表示第i条边
int head[N]; //head[i]表示i点的最后一条边的编号
void add(int u,int v,int w)
{
e[++tot].next=head[u];
e[tot].v=v;
e[tot].w=w;
head[u]=tot; //把当前新加的边作为第一条边
}
int main()
{
scanf("%d%d",&n,&m);
int u,v,w,k;
tot=0;
met(head,0);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
for(int i=1;i<=n;i++){
int k=head[i];
while(k!=0){
printf("%d %d %d\n",i,e[k].v,e[k].w);
k=e[k].next;
}
}
}