图论重造-图的存储(邻接表模版)

来源:互联网 发布:林肯大陆 知乎 编辑:程序博客网 时间:2024/06/01 07:27

邻接矩阵
没什么好说的,n个点n*n的矩阵,a[i][j]表示i与j相连。
当n很大,图很稀疏时,会翻车。
一般点数|v|<=5000 可使用。
找邻接点慢,要枚举每一个点。
优点是写起来真的很简单。

静态邻接表
代码书写较复杂,找邻接点快。
采用动态存储结构(指针或用数组模拟)
一般点数|v|大于等于5000,并且边的个数不是很多的时候,用邻接表,并且现在一般都是用数组来模拟。
要注意如果是无向图,e数组要开2倍。

存储:

struct edge{    int y,v,next;       //y表示这条边的终点编号,v是权值;};                  //next表示同起点下条边的编号是多少edge e[maxm+10];  //边表。int linkk[maxn+10];  //起点表 link[i]表示由i出去的第一条边的下标是多少void insert(int ss,int ee,int vv)//ss为起点,ee为终点,vv为权值。{      e[++t].y=ee; e[t].v=vv;     //t表示有t条边,是个全局变量。    e[t].next=linkk[ss]; linkk[ss]=t;}void init(){    scanf("%d %d %d",&n,&p,&m);    for (int i=0;i<m;i++)    {        int xx,yy,zz;        scanf("%d%d%d",&xx,&yy,&zz);        insert(xx,yy,zz);        insert(yy,xx,zz);  //这里插入的是无向图,所以两条边都要插入。    }    }    

对不起,偷懒了,直接ctrl+c了ppt。

遍历某个点的每一条边:

for (int i=linkk[k];i;i=e[i].next)

注,邻接矩阵dfs的效率是O(n^2),而邻接表是O(n+m)。

例题

警察抓到了n个罪犯,警察根据经验知道他们属于不同的犯罪团伙,却不能判断有多少个团伙,但通过警察的审讯,知道其中的一些罪犯之间相互认识,已知同一犯罪团伙的成员之间直接或间接认识,有可能一个犯罪团伙只有一个人。请你根据已知罪犯之间的关系,确定犯罪团伙的数量。已知罪犯的编号从1至n。
n(<10000,罪犯数量)m(<50000,关系数量)

邻接表遍历。

#include<bits/stdc++.h>using namespace std;struct edge{    int y;    int next;}e[200020];int linkk[10050]={};int flag[10050]={};int tot=0;int ans=0;int n,m;inline void dfs(int x){    flag[x]=1;    for(int i=linkk[x];i;i=e[i].next)       if(!flag[e[i].y]) dfs(e[i].y);}inline void work(){    for(int i=1;i<=n;i++)    {        if(!flag[i])        {            ans++;            dfs(i);        }    }}inline void insert(int x,int y){    e[++tot].y=y;    e[tot].next=linkk[x];linkk[x]=tot;    return;}int main(){    cin>>n>>m;    for(int i=1;i<=m;i++)     {        int x,y;        cin>>x>>y;        insert(x,y);insert(y,x);    }    work();    cout<<ans;    return 0;}

////▽/*//

原创粉丝点击