图的存储
1.简单储存 (邻接矩阵):第一行输入n与m,表示n个点,m条边然后输入 u,v 表示 u与v相连,代码:
int vis[500][500];
void save(int u, int v)
{
int m,n;
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%d%d",&u,&v);
vis[u][v]=1;
vis[v][u]=1;//双向关系
}
}
这个邻接矩阵优点就是容易理解,缺点就是内存太大(n*n),适用于点少的情况。
2.邻接表
将每一个点可能连到的所有的点,储存下来,成为一个长表。
邻接表首先需要一个结构体:
struct node{
int to;//定义节点
node *next;
};
node *head[10000];//头结点数组
然后需要用一个函数,实现每个点之间的关系:
struct node{
int to;//定义节点
node *next;//存储连的下一个节点
};
node *head[10000];//头结点数组
void addedge(int u,int v)
{
node *p=(node*)malloc(sizeof(node));
p->to=v;
p->next=head[u];//头插法建立链表
//head[u]可理解为head的下一个,所以先让新来的next指向他,然后新来的成为头指针。每次都进行这样循环,即创建完链表。
head[u]=p;
}
int main()
{
int m,n;
int u,v;
scanf("%d%d",&m,&n);
while(m--)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
return 0;
}
如果还有不懂,就看以下上面的表。
邻接表储存图是比较常用的一种方法,优点就是动态内存分配,缺点就是,时间长,指针容易混乱。
3.链式前向星
const int maxn=1e6+5;
const int INF=1e9;
struct node{
int e;//记录可以到达地址
int w;//到达e的距离或者时间
int next;//储存下一个地址
}egde[maxn];
int head[maxn];//头指针数组
ll cnt=0;//记录指针后移
void addedge(int u,int v,int w)
{
edge[cnt].e=v;//u->v;
edge[cnt].w=w;
edge[cnt].next=head[u];//把这一组数据放到u后面;
head[u]=cnt++;
/*或者还有一种写***出警告,但不报错
edge[cnt]={v,w,head[u]};
head[u]=cnt++;*/
}
不懂的话,再参考一下我盗来的图。
but 现在出现了问题:
如何访问?我们可以直到,肯定是i=head[u](即他最后一次的cnt)然后慢慢向前访问,与头插法类似,但是指针可以赋予为空指针,让他停止。但是链式前向星怎么让他停止呢?我们可以对头指针数组进行赋初值,一旦碰到这个值后停止。所以:
void restart()
{
memset(head,-1,sizeof(head));
cnt=0;//多组输入中这个而一定要加;
}
void Search(int u)//访问u后面链接了哪几个点
{
for(int i=head[u];i!=-1;i=edge[i].next)
printf("u->%d need %d\n",edge[i].e,edge[i].w);
}
结束,谢谢阅读。