用DFS和BFS求连通分量(邻接表的实现与应用)
来源:互联网 发布:淘宝花呗怎么还款 编辑:程序博客网 时间:2024/05/07 02:27
用DFS和BFS求连通分量(邻接表的实现与应用)
本文内容改编自《挑战程序设计竞赛(第2弹)》12.5节
问题描述
给出朋友关系,判断从指定人物出发能否通过双向朋友链抵达目标人物。
输入
第一行输入总人数n以及朋友关系数m
人的编号从0到n-1。
接下来m行输入朋友关系,每个朋友关系占一行。
1个朋友关系包含s、t两个整数,表示s和t为朋友。
接下来一行输入问题数q。再接下来q行输入问题
各问题为两个整数s、t。表示“从s能否抵达t?”
输出
如果从s出发能抵达t就输出yes,否则输出no,每个问题的回答占1行。
限制
1 < n < 100000, 0 < m < 100000, 1 < q < 10000
样例输入
10 9
0 1
0 2
3 4
5 7
5 6
6 7
6 8
样例输出
yes
yes
no
解题思路
这道题就是求给定的图的连通分量问题,可以用“种子填充”的思想来解决此题。
对图中每一个结点进行深度优先搜索,并在此过程中对还没有填色的结点填填色。
如果两个结点有相同的颜色,那么这两个结点就是连通的。
于是O(1)时间就可以判断指定两个结点是否连通。
核心算法就是DFS。主要数据结构就是邻接表,用来存储图的信息。
在邻接表上的DFS需要需要对每个顶点,每个边都要访问一次,算法复杂度为
O(|V|+|E|)
邻接表的实现
在C++中,用vector可以轻松的实现邻接表。
vector<int> G[100]; //表示100个顶点的邻接表 G[u].push_back(v); //从顶点u向顶点v画边 //搜索与顶点相邻的顶点v for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; //... }
邻接表的优缺点
优点:只需要与边数成正比的空间
缺点:难以有效地删除边
若u的相邻顶点数量为n,需要消耗O(n)来搜索邻接表。
代码实现
#include <bits/stdc++.h>using namespace std;const int MAX_N = 100000;int n;vector<int> G[MAX_N];int color[MAX_N]; //从结点r开始DFS,并填充颜色cvoid dfs(int r, int c){ color[r] = c; for (int i = 0; i < G[r].size(); i++) { int v = G[r][i]; if (color[v] == -1) { dfs(v, c); //相邻结点v未填色,则继续搜索 } }}void AssignColor(){ int id = 0; memset(color, -1, sizeof(color)); //初始化color数组,-1表示未填色 for (int u = 0; u < n; u++) { if (color[u] == -1) dfs(u, id++); //对未填色的结点开始DFS }}int main(){ int m, s, t; while (cin >> n >> m) { //创建邻接表 for (int i = 0; i < m; i++) { cin >> s >> t; G[s].push_back(t); G[t].push_back(s); } //填色开始 AssignColor(); int q; cin >> q; for (int i = 0; i < q; i++) { cin >> s >> t; if (color[s] == color[t]) { cout << "yes" << endl; } else { cout << "no" << endl; } } } return 0;}
其中void dfs()还有另外一种实现方法,就是显式地使用栈来实现DFS。
当然这道题也可以用广度优先搜索(BFS),部分代码如下
void bfs(int r, int c){ queue<int> Q; Q.push(r); color[r] = c; while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (color[v] == -1) { color[v] = c; Q.push(v); } } }}void AssignColor(){ int id = 0; memset(color, -1, sizeof(color)); //初始化color数组,-1表示未填色 for (int u = 0; u < n; u++) { if (color[u] == -1) bfs(u, id++); //对未填色的结点开始BFS }}
- 用DFS和BFS求连通分量(邻接表的实现与应用)
- 图的邻接表 表示 DFS 和BFS C++实现
- 求连通分量(DFS)
- 用邻接链表实现BFS算法和DFS算法
- 利用BFS求图的连通分量
- 邻接表 的 DFS 与 BFS
- 23.基于 邻接表 dfs 的 求连通分支
- [BFS][连通分量]求连通分量
- (java)DFS求连通分量的个数
- 数据结构_图_邻接表做存储结构实现求无向图的连通分量_C++实现
- 数据结构之——用C++实现邻接表的DFS与BFS
- 图的遍历(BFS、DFS的邻接矩阵和邻接表实现)
- 用邻接表存储有向图实现的dfs和bfs
- 图的BFS,DFS(邻接表)
- Tarjan求强连通分量的讲解与实现
- 图(邻接表)的遍历——DFS(深度优先搜索)和BFS(广度优先搜索)和连通图
- hdu1269--求强连通分量个数--tarjan--图的静态邻接表
- 通过BFS 和 DFS两种方法找无向图的连通分量
- 【备忘】达内,韩顺平,马士兵,孙鑫,郝斌等Java基础视频教程下载
- redis整合ssm
- 进程编程中的vfork
- 工厂方法模板(java编程思想 使用匿名内部类)
- 对OMAP-L138的PSC模块的理解
- 用DFS和BFS求连通分量(邻接表的实现与应用)
- 总结69
- 网络攻击技术(三)——Denial Of Service
- PHP版本--HTTP session cookie原理及应用(上)cookie 篇
- 【树莓派开发】 Qt Creator中,include路径包含过程(或如何找到对应的头文件)
- fork与vfork的区别
- 坚持#第119天~利索,真的,好喜欢利索
- 【备忘】北风网Java必备JAVA语言基础与OOP入门(骑士飞行棋门禁系统)
- 链表的基本排序