图的存储
图的存储方式
在说最短路之前,先介绍一下图的几个存储方式:主要有vector、邻接表和链式前向星三种存储方式。其中会牵扯到稀疏图和稠密图的概念,稠密图指点的个数的平方和边的个数是一个数量级的(\(n^2 ≈ m\)),两者数量级类似别称为稀疏图。
<1:vector存图
vector适合存稀疏图,直接看代码:
vector<int> G[maxn];
for(int i=1;i<=m;++i){
cin>>from>>to;
G[from].push_back(to);
G[to].push_back(from); //无向图一条边会被存两次
}
<2:领接表存图(有错,有时间给改一改)
领接表适合存稠密图,可以用数组模拟出来,看代码:
int head[maxn]; //头结点数组
int ne[maxn]; //邻接点数组
for(int i=1;i<=n;++i)
head[i]=-1; //初始化
for(int i=1;i<=m;++i)
{
int a,b,val;
cin>>a>>b>>val;
ne[a]=head[a];
head[a]=i;
}
❤️:链式星向前
链式星向前其实就是邻接表的改进版本。
const int maxn=1e5+10;
struct node
{
int nex,to,val;
}Edge[maxm]; //nex表示与当前边起点一样的另一条边在弄的数组中的位置,to表示边的终点
int head[maxn]; //head[i]表示从i出发的点的链表的第一个点在node数组中的位置。
int tot=0; //当前已有边的个数。
void Add(int from,int to,int val)
{
Edge[++tot].to=to;
Edge[tot].val=val;
Edge[tot].nex=head[from]; //当前结点指向以前的头结点
head[from]=tot; //当前结点变为头结点
}
void Use(int i) //遍历起点为i的链表
{
int t=head[i];
while(t!=-1)
{
cout<<"from "<<i<<"to "<<Edge[t].to<<"is "<<Edge[t].val<<endl;
t=Edge[t].to;
}
}
int main()
{
int from,to,n;
memset(head,-1,sizeof(head));
memset(Edge,-1,sizeof(node));
while(cin>>from>>to>>n,from&&to&&n)
Add(from,to,n);
int i;
cin>>i;
Use(i);
}