一定要考虑到非连通图的情况。已经在这里栽了好多跟头了!!!
目录
今天也是为了cc,努力奋斗的一天ヾ(≧▽≦*)o
1. 图的存储
邻接矩阵
- 适合顶点数 小于1000;
- 适合每两个顶点之间 只有一条边 的情况;
- 其实相比于邻接表,这个已经很少用到了;
邻接表
- 适合顶点数 大于1000
- 非常常用,而且需要结合结构体一起使用
- 能够用于两个结点之间 存在多条边 的情况
链式前向星
- 链式前向星讲解
- 普通学校的机试基本不会用到这个东西。。。
2. 深度优先搜索(DFS)
基本思想
常量定义
const int MAXV = 1000; //最大顶点数
const int INF = 10000000000; //设INF为一个很大的数
注意:两者都需要一个vis
数组来保存是否可以访问。以及不可达的判断!
邻接矩阵实现DFS
/*
邻接矩阵版
*/
int n,G[MAXV][MAXV]; //n为顶点数,MAXV为最大顶点数
bool vis[MAXV] = {false}; //如果顶点i已经被访问了,则vis[i]==true。初值为false
void DFS(int u,int depth){ //u设置为当前访问的顶点标号,depth为深度
vis[u] = true; //设置u已被访问
//如果需要对u进行一些操作,可以在这里进行
//下面对所有从u出发能够到达的分支顶点进行枚举
for(int v = 0;v < n;v++){ //对每个顶点v
if(vis[v] == false && G[u][v] != INF){ //如果v未被访问,且u可到达v
DFS(v,depth+1); //访问v,深度加1
}
}
}
void DFSTrave(){ //遍历图G
for(int u = 0; u < n;u++){ //对每个顶点u
if(vis[u] == false){ //如果u未被访问
DFS(u,1); //访问u和u所在的连通块,1代表初始为第一层
}
}
}
邻接表实现DFS
/*
邻接表版
*/
vector<int> Adj[MAXV]; //图G的邻接表
int n; //n为顶点数,MAXV为最大顶点数
bool vis[MAXV] = {false}; //如果顶点i已被访问,则vis[i]==true,初值为false
void DFS(int u,int depth){ //u为当前访问的顶点坐标,depth为深度
vis[u] = true; //设置u已被访问
//如果需要对u进行一些操作,可以在此处进行
for(int i=0;i<Adj[u].size();i++){ //对从u出发可以到达的所有顶点v
int v = Adj[u][i];
if(vis[v] == false){ //如果v未被访问
DFS(v,depth+1); //访问v,深度加一
}
}
}
void DFSTrave(){ //遍历图G
for(int u=0;u<n;u++){ //对每一个顶点u
if(vis[u] == false){ //如果u未被访问
DFS(u,1); //访问u和u所在的连通块,1为初始为第一层
}
}
}
广度优先搜索(BFS)
注意:这里的bool
数组是用于标记是否已经加入了队列,而不是是否已经访问了,因为加入队列并不代表会被立即访问,可能还需要再等一下才能访问。
基本思路
BFS(u){ //遍历u所在的连通块
queue q; //定义队列q
将u入队;
inq[u] = true; //设置u已经被加入到队列中
while(q非空){ //只要队列非空
取出q的队首元素u进行访问;
for(从u出发可以到达的所有顶点v) //枚举从u能够直接到达的顶点v
if(inq[v] == false){ //如果v未曾加入过队列
将v入队;
inq[v] = true; //设置v已被加入到队列
}
}
}
BFSTrave(G){ //遍历图G
for(G的所有顶点u) //枚举G的所有顶点u
if(inq[u] == false){ //如果u未曾加入过队列
BFS(u); //遍历u所在的连通块
}
}
邻接矩阵实现BFS
int n,G[MAXV][MAXV]; //n为顶点数,MAXV为最大顶点数
bool inq[MAXV] = {false}; //若顶点i未曾如果队列,则inq[i]==true,初值为false
void BFS(int u){ //遍历u所在的连通块
queue<int> q; //定义队列q
q.push(u); //将初始点u入队
inq[u] = true; //设置u已被加入过队列
while(!q.empty()){ //只要队列非空
int u = q.front(); //取出队首元素
q.pop(); //将队首元素出队
for(int v = 0;v<n ;v++){
if(inq[v] == false && G[u][v] != INF){
q.push(v); //将v入队
inq[v] = true; //标记v为已被加入队列
}
}
}
}
void BFSTrave(){ //遍历图G
for(int u=0;u<n;u++){ //枚举所有的顶点
if(inq[u] == false){ //如果u未曾加入过队列
BFS(q); //遍历u所在的连通块
}
}
}
邻接表实现BFS
vector<int> Adj[MAXV]; //图G,Adj[u]存放从顶点u出发可以到达的所有顶点
int n; //n为顶点数,MAXV为最大的顶点数
bool inq[MAXV] = {false}; //若顶点i曾入队列,则inq[i]==true。初值为false
void BFS(int u){ //遍历单个连通块
queue<int> q; //定义队列q
q.push(u); //将初始点u入队
inq[u] = true; //设置u已被加入过队列
whiel(!q.empty()){ //只要队列非空
int u = q.front(); //取出队首元素
q.pop(); //将队首元素出队
for(int i=0;i<Adj[u].size();i++){ //枚举从u出发能够到达的所有顶点
int v = Adj[u][i];
if(inq[v] == false){ //如果v未曾加入过队列
q.push(v); //将v入队
inq[v] = true; //标记v为已被加入过队列
}
}
}
}
void BFSTrave(){ //遍历图G
for(int u=0;u<n;u++){ //枚举所有的顶点
if(inq[u] == false){ //如果u未曾加入过队列
BFS(q); //遍历u所在的连通块
}
}
}