图
简单来说图就是由一些点与一些边组成,点与点可以通过边连接每条边可以由权值,那么通过题目的输入如何来储存一张图呢?
图的存储
结构体
要解决这个问题,我们首先需要知道需要储存图的那些信息,对于一组数据会给出起点、终点、边长。
那么最简单的方法就是用一个结构体数组来存储所有的信息。
struct edge{
int a,b,w;//起点为a,终点为b,边权为w
}e[maxn];
int main()
{
for(int i=1;i<=edge_num;i++)
{
int a,b,w;
cin>>a>>b>>w;
e[i].a=a,e[i].b=b,e[i].c=w;
//e[i]={a,b,w};
}
}
这样做显然是可以存储下我们想要的信息的,但是如果我们想要知道两个点之间是否之间相连,那我们只能通过遍历所有边的方式来获取这个信息。时间复杂度是O(n)
//a 与b是否之间是否有边?
int have_edge(int a,int b){
for(int i=1;i<=edge_num;i++)
{
if(e[i].a==a&&e[i].b==b)
return e[i].w;
}
}
邻接矩阵
为了快速可以判断两个点之间是否有边,我们可以用邻接矩阵的方式来存储图。
int gra[N][N];//N为点的个数
void get_edge()
{
memset(gra,0x3f,sizeof(gra));//初始化所有点不可达
for(int i=1;i<=edge_num;i++)
{
int a,b,w;
cin>>a>>b>>w;
gra[a][b]=w;
}
}
这样我们判断a、b是否有边就可以在O(1)的时间内快速判断了。邻接矩阵的劣势也很明显,那就是空间复杂度需要O(n2)如果在稀疏图中就会浪费大量的空间,并且在点数超过10000时就会超内存无法开二维数组。
邻接表
请看下面一张图,邻接表就是只存储一个点之间相连的另外一个点以及其边长,这里的结构类似于链表,也就是每个顶点都作为链表的头节点,理解好了这一点我们就有很多方式来实现这样一个过程了。
int h[N],e[N],ne[N],idx,w[N];//h[i]代表的是第i个节点的邻接表,idx可以理解为链表中的地址 e[idx]存放的是a节点可达的节点b,ne则是下一个节点的idx。
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;//头插法加边
}
void get_pointEdge(int a)//获取节点a所有相连的边的权值和
{
int sum=0;
for(int i=h[a];i!=-1;i=ne[i])
{
int ver=e[i];
sum+=w[i];
}
}
void innit()
{
memest(h,-1,sizeof(h));//-1作为NUll;
}
链式前向星
与邻接表差不多,由于我写的比较少,大家可以选择着学习。