图的BFS中关于visit数组的位置问题

图的BFS中关于visit访问位置的问题

1, 图的BFS两种代码

1.1,代码1

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int G[1010][1010];
bool visit[1010];
int vex, L; 
int height[1010];
void bfs(int root, int &cnt){ 
	queue<int> q;
	q.push(root);
	height[root]=1;
	visit[root]=true; // 1
	while(!q.empty()){
		int cur = q.front();
		q.pop();
		int cur_height = height[cur];
		if(cur_height<=L+1){
			++cnt;
		}
		for(int v=1;v<=vex;++v){
			if(G[cur][v]!=inf&&visit[v]==false){
				height[v] = height[cur]+1;
				visit[v]=true;  // 2
				q.push(v);
			}
		}
	}
}

1.2,代码2(这个版本错误)

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int G[1010][1010];
bool visit[1010];
int vex, L; 
// 1: 3 2 3 4±íʾ 1×·2,3,4 
int height[1010];
void bfs(int root, int &cnt){  
	queue<int> q;
	q.push(root);
	height[root]=1;
	while(!q.empty()){
		int cur = q.front();
		q.pop();
		visit[cur]=true;  // 3
		int cur_height = height[cur];
		if(cur_height<=L+1){
			++cnt;
		}
		for(int v=1;v<=vex;++v){
			if(G[cur][v]!=inf&&visit[v]==false){
				height[v] = height[cur]+1;
			
				q.push(v);
			}
		}
	}
}

2,代码2错误原因分析



代码1成功的防止重复的结点进入队列。 但是代码2没有做到。

举例: 假设有一个含3个结点的环, 标号A,B,C。 遍历顺序按字母大小。
 起点是A。

代码1 访问顺序: A->B->C
代码2 访问顺序: A->B->C->C。 // 读者可以简单思考一下

3,小结

	上面是图的BFS两种版本代码, 初学者看到这两个版本代码,可能认为是一样的。
笔者也有这样的疑惑。第一次理解后又忘了,第二次思考这个问题忘了没想出来。
 所以这里再记录一遍。
 	像图的BFS遍历是一种非常经典的算法。 也有其成熟的板子。 要记住
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用 BFS(广度优先搜索)算法来求解无向的最大团的 C 代码实现: ``` #include <stdio.h> #include <stdlib.h> #define N 100 // 最大顶点数 int G[N][N], visit[N], cur[N], max[N], max_size = 0; // G: 无向邻接矩阵, visit: DFS 的访问数组 // cur:当前团的节点集合,max:当前最大团的节点集合,max_size:当前最大团的大小 // 判断一个节点集合是否与给定的节点 u 相邻 int check_v(int u, int cur_size) { int i; for (i = 0; i < cur_size; ++i) { if (!G[u][cur[i]]) { return 0; } } return 1; } // 判断一个团是否为最大团 void check_max(int cur_size) { if (cur_size > max_size) { // 如果当前团更大,则更新最优解 int i; for (i = 0; i < cur_size; ++i) { max[i] = cur[i]; } max_size = cur_size; } } // 使用 BFS(广度优先搜索)算法来求最大团 void max_clique_bfs() { int cur_size, u, v, i, j, tail = 0; int queue[N]; // 队列 for (i = N - 1; i >= 0; --i) { // 倒序遍历顶点 cur_size = 1; cur[0] = i; // 当前的团只有一个节点 i queue[tail++] = i; // 把 i 放入队列 while (tail > 0) { // BFS 基本结构,依次访问队列的节点 u = queue[--tail]; for (v = 0; v < N; ++v) { if (G[u][v] && !visit[v] && check_v(v, cur_size)) { // 以 BFS 的方式依次遍历所有与 u 相邻的节点 v visit[v] = 1; cur[cur_size++] = v; // 把 v 加入当前的团 queue[tail++] = v; // 把 v 放入队列 } } } check_max(cur_size); // 检查当前生成的团是否为最大团 max[i] = -1; max_size = 0; } } int main() { int n, m, i, j; scanf("%d%d", &n, &m); // n 为顶点数,m 为边数 for (i = 0; i < n; ++i) { for (j = 0; j < n; ++j) { G[i][j] = 0; // 初始化邻接矩阵为 0 } } for (i = 0; i < m; ++i) { int u, v; scanf("%d%d", &u, &v); // 读入边 --u; --v; // 将节点编号转化为从 0 开始的编号 G[u][v] = G[v][u] = 1; // 如果 u 和 v 相邻,则 G[u][v] 和 G[v][u] 均为 1 } max_clique_bfs(); // 求解最大团 printf("Size of maximum clique is %d\n", max_size); printf("Vertices in the maximum clique are: "); for (i = 0; i < max_size; ++i) { printf("%d ", max[i] + 1); // 将最优解节点的编号重新转化为从 1 开始的编号输出 } printf("\n"); return 0; } ``` 以上代码实现了使用 BFS(广度优先搜索)算法来求解无向的最大团。算法的基本思路是从的每一个节点开始,依次生成每一个包含该节点的团,并检查其是否为最大团。为了避免重复,当遍历一个节点 u 时,只考虑它的编号比 u 更大的节点 v 作为当前团的元素,这样可以保证每个团只被遍历一次。在判断一个节点集合是否与给定的节点 u 相邻时,只需要检查这些节点之间是否存在边即可。由于 BFS 算法遍历顺序是按照层数依次访问所有节点,因此可以保证通过 BFS 算法所生成的团一定是最大团的一员。最后,只需要从所有最大团选择一个节点数最多的团作为最优解即可。 注意:上面代码的变量 G 是一个邻接矩阵,其 G[u][v] 和 G[v][u] 分别表示节点 u 和节点 v 是否相邻。在使用该代码时,需要将的所有节点编号都减一,以满足数组下标从 0 开始的要求。另外,由于该算法的时间复杂度为 O(2^n),因此只适用于节点数不太多(通常小于 40)的。如果节点数过多,则建议使用其他的算法,例如 Bron-Kerbosch 算法等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值