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

邻接矩阵
没什么好说的,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;
}

▽/*//

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值