用BFS 遍历图

参考资料:《算法笔记》
使用工具:队列queue

思想:

通过反复取出队首顶点,将该顶点能到达的未曾加入队列的顶点入队,直到队列为空时遍历结束,

具体实现:

如果图是连通图,那么一次BFS就能遍历完成所有顶点:

bfs(u){	//遍历u所在的连通块
	queue q;
	将u入队;
	inq[u] = true;	//设置q已经加入过队列
	while(q非空){
		取出队首元素进行访问;
		for(从u出发能到达的所有顶点v){
			if(未加入过队列){
				将v入队;
				标记v加入过队列;
			}
		}
	}
}
BFStrave(G){	//遍历图G
	for(G的所有顶点u){
		if(inq[u] == false)	//u未加入过队列
			BFS(u);
	}	
}

邻接矩阵实现:

void bfs(int u){
	queue<int> q;
	q.push(u);
	inq[u] = true;
	while(!q.empty()){
		int u = q.front();	//取出队首
		q.pop();	//队首出队
		for(int v = 0; v < n; v ++){
			if(g[u][v] != INF && inq[v] == false){
				q.push(v);
				inq[v] = true;
			}			
		} 
	}
} 

void BFStravel(){	//遍历图g 
	for(int i = 0; i < n; i ++ ){
		if(inq[i] == false){
			bfs(i);
		}
	}
}

邻接表实现:

邻接表里adj[u][i]是u已经能到达的顶点,所以不需要判断是否能到达;

void bfs(int u){
	queue<int> q;
	q.push(u);
	inq[u] = true;
	while(!q.empty()){
		int u = q.front();	//取出队首
		q.pop();	//队首出队
		for(int i = 0; i < adj[u].size(); i ++){
			int v = adj[u][i];
			if(inq[v] == false){	//肯定能到达,不需要判断 
				q.push(v);
				inq[v] = true;
			}			
		} 
	}
} 

void BFStravel(){	//遍历图g 
	for(int i = 0; i < n; i ++ ){
		if(inq[i] == false){
			bfs(i);
		}
	}
}

补充情况:在给定bfs的初始点的情况下,可能要输出该连通块内其他顶点的层号,这时候需要定义结构体,在其中放顶点的编号和层号:

struct node{
	int v, layer;	//编号 层号
}

vector<node> adj[maxn];

如果当前层号是L,那么它所出边的终点的层号都为L+1;
此时的邻接表实现:

void bfs(int s){	//s为起点编号 
	queue<node> q;
	node start;	//新建起点,编号为s 层数为0 
	start.v = s;
	start.layer = 0; 
	
	q.push(start);
	inq[start.v] = true;
	while(!q.empty()){
		node topnode = q.front();	//取出队首
		q.pop();	//队首出队
		int u = topnode.v;	//队首的编号 
		for(int i = 0; i < adj[u].size(); i ++){
			 
			node next = adj[u][i];
			next.layer = topnode.layer+1;	//层数+1 
			if(inq[next.v] == false){	//肯定能到达,不需要判断 
				q.push(next);
				inq[next.v] = true;
			}			
		} 
	}
} 

PAT 相关题目:

PAT 1076 Forwards on Weibo (30分)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值