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