图的存储

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);
}

结束,谢谢阅读。