无向图中两点(x1,y1)(x2,y2)是否连通(bfs&并查集)两种方法解决(c++)

1.bfs

//bfs看两点是否联通
#include <bits/stdc++.h>
using namespace std;

// 用于BFS的辅助函数,检查坐标是否在网格内
bool isValid(int x, int y, int n, int m) {
	return x >= 0 && x < n && y >= 0 && y < m;
}

// BFS函数,判断两个点是否连通
bool bfs(const vector<vector<int>>& grid, int startX, int startY, int targetX, int targetY) {
	int n = grid.size();
	int m = grid[0].size();
	
	// 访问标记数组
	vector<vector<bool>> visited(n, vector<bool>(m, false));
	
	// 队列用于存储待访问的节点
	queue<pair<int, int>> q;
	
	// 初始点入队
	q.push({startX, startY});
	visited[startX][startY] = true;
	
	while (!q.empty()) {
		auto front = q.front();
		q.pop();
		
		int x = front.first;
		int y = front.second;
		
		// 检查是否到达目标点
		if (x == targetX && y == targetY) {
			return true; // 连通
		}
		
		// 检查上下左右四个方向
		vector<pair<int, int>> directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
		for (auto& dir : directions) {
			int newX = x + dir.first;
			int newY = y + dir.second;
			
			if (isValid(newX, newY, n, m) && !visited[newX][newY] && grid[newX][newY] == 0) {
				q.push({newX, newY});
				visited[newX][newY] = true;
			}
		}
	}
	
	return false; // 不连通
}

int main() {
	// 示例网格,0 表示可通行,1 表示障碍物
	vector<vector<int>> grid = {
		{0, 0, 1, 0, 0},
		{0, 1, 0, 1, 0},
		{0, 0, 0, 0, 0},
		{1, 1, 0, 1, 0},
		{0, 0, 0, 0, 0}
	};
	
	int startX = 0; // 起始点 x 坐标
	int startY = 0; // 起始点 y 坐标
	int targetX = 4; // 目标点 x 坐标
	int targetY = 4; // 目标点 y 坐标
	
	if (bfs(grid, startX, startY, targetX, targetY)) {
		cout << "Points are connected." << endl;
	} else {
		cout << "Points are not connected." << endl;
	}
	
	return 0;
}

2.并查集

#include <iostream>
#include <vector>
using namespace std;

class UnionFind {
private:
	vector<int> parent;
	vector<int> rank;
	
	int find(int x) {
		if (x != parent[x]) {
			parent[x] = find(parent[x]); // 路径压缩
		}
		return parent[x];
	}
	
public:
	UnionFind(int n, int m) : parent(n * m), rank(n * m, 1) {
		for (int i = 0; i < n * m; ++i) {
			parent[i] = i; // 初始时,每个节点的父节点是它自己
		}
	}
	
	void unionSets(int x, int y) {
		int rootX = find(x);
		int rootY = find(y);
		if (rootX != rootY) {
			if (rank[rootX] < rank[rootY]) {
				parent[rootX] = rootY;
			} else if (rank[rootX] > rank[rootY]) {
				parent[rootY] = rootX;
			} else {
				parent[rootY] = rootX;
				rank[rootX]++;
			}
		}
	}
	
	bool isConnected(int x, int y) {
		return find(x) == find(y);
	}
};

bool isValid(int x, int y, int n, int m) {
	return x >= 0 && x < n && y >= 0 && y < m;
}

int main() {
	vector<vector<int>> grid = {
		{0, 0, 1, 0, 0},
		{0, 1, 0, 1, 0},
		{0, 0, 0, 0, 0},
		{1, 1, 0, 1, 0},
		{0, 0, 0, 0, 0}
	};
	
	int n = grid.size();
	int m = grid[0].size();
	int x1 = 0, y1 = 0; // 起始点坐标
	int x2 = n - 1, y2 = m - 1; // 目标点坐标
	
	UnionFind uf(n, m);
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			if (grid[i][j] == 0) {
				if (i + 1 < n && grid[i + 1][j] == 0) {
					int id1 = i * m + j;
					int id2 = (i + 1) * m + j;
					uf.unionSets(id1, id2);
				}
				if (j + 1 < m && grid[i][j + 1] == 0) {
					int id1 = i * m + j;
					int id2 = i * m + (j + 1);
					uf.unionSets(id1, id2);
				}
			}
		}
	}
	
	bool connected = uf.isConnected(y1 * m + x1, y2 * m + x2);
	cout << "Points (" << x1 << ", " << y1 << ") and (" << x2 << ", " << y2 << ") are "
	<< (connected ? "connected" : "not connected") << "." << endl;
	
	return 0;
}

3.总结

对于这两种算法,它们的时间复杂度在最坏情况下都可以达到 O(n * m)。然而,在实际应用中,由于并查集的路径压缩优化,它在处理大规模数据时通常比 BFS 更高效。BFS 可能需要遍历更多的节点,尤其是在网格中有大量障碍物时。而并查集则通过减少查找操作的次数来提高效率。

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来回答这个问题。 创建一个含8个顶点、15条边的无向图g,可以用邻接矩阵或邻接表来表示。这里我用邻接矩阵表示,如下所示: ``` 1 2 3 4 5 6 7 1 1 1 1 1 1 2 1 1 1 1 3 1 1 1 1 4 1 1 1 1 5 1 1 1 6 1 1 7 1 1 ``` 其,每一行和每一列代表一个顶点,如果两个顶点之间有边相连,则对应位置上的值为1,否则为。比如,第一行表示顶点与顶点1、2相连。 接下来,我们可以分别对g进行dfs和bfs两种遍历。 dfs遍历: 从一个起始顶点开始,沿着一条路径遍历到底,直到不能再继续为止,然后回溯到前一个顶点,再选择另一条路径继续遍历,直到所有顶点都被遍历到为止。 以顶点为起始点,dfs遍历g的过程如下: ``` dfs() dfs(1) dfs(2) dfs(3) dfs(4) dfs(5) dfs(7) back to 5 back to 4 back to 3 back to 2 back to 1 dfs(2) dfs(3) dfs(4) dfs(5) dfs(7) back to 5 back to 4 back to 3 back to 2 dfs(3) dfs(4) dfs(5) dfs(7) back to 5 back to 4 back to 3 back to dfs finished ``` 可以看到,dfs遍历的顺序是-1-2-3-4-5-7,然后回溯到5,再回溯到4,以此类推,最后回到起始点,遍历结束。 bfs遍历: 从一个起始顶点开始,先访问它的所有邻居顶点,然后再访问它们的邻居顶点,以此类推,直到所有顶点都被遍历到为止。 以顶点为起始点,bfs遍历g的过程如下: ``` bfs() visit visit 1 visit 2 visit 3 visit 4 visit 5 visit 6 visit 7 bfs finished ``` 可以看到,bfs遍历的顺序是-1-2-3-4-5-6-7,按照层次逐个访问顶点,直到所有顶点都被遍历到为止。 希望我的回答能够帮到你,如有不清楚的地方,欢迎继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值