C++通过邻接矩阵求连通分量(BFS)
在求图的连通分量时可能会碰见的问题--已经构造出了邻接矩阵,但不知道怎么求连通分量。这里选择用BFS来求连通分量。
在开始前先要说明下一些基础知识。
连通分量
如上图图一的连通分量为1,而去掉其中一条边后可以得到图二,而图二的连通分量为2。相当于求一个图里有多少个连通图。
BFS求连通分量
假设我们现在已经得到了一个连通矩阵(如下),可以知道该图一共4个节点且存在连通分量(矩阵不全为0)。
0 1 1 0
1 0 0 0
1 0 0 0
0 0 0 0
那么思路是这样的:设置一个变量sum来记录连通分量的数量。然后去遍历这四个节点,每次遍历都去寻找它的邻边;并把在邻边上的点设置为“已访问”。在第一次遍历时如果这个节点已经被访问过了就跳过;如果没有被访问过sum就需要加一并查找该节点有没有邻边。
有了思路后就剩“如何实现查找该节点的邻边”了,用DFS和BFS都行,这里用的BFS。
其中x为节点编号,n为总的节点个数,mat为邻接矩阵,visit为记录节点是否已被访问过的数组。每次BFS时先把该节点设置为已访问并入队。然后去查找它邻边上的节点(通过遍历mat[cur]这一行,如果在cur这一行的第i个位置为1,就说明编号为cur的节点与编号为i的节点存在邻边),如果该节点没被访问过且存在邻边,入队并设置为已访问。
void BFS(int x,int n,int**mat,int*visit)
{queue<int>Q;Q.push(x);visit[x] = 1;while (!Q.empty()){int cur = Q.front();Q.pop();for (int i = 0;i < n;i++){if (visit[i]==0 && mat[cur][i]){visit[i] = 1;Q.push(i);}}}
}
最后遍历每一个节点再根据是否已被访问去调用BFS即可。
for (int i = 0;i < n;i++){if (visit[i] == 0){BFS(i,n,mat,visit);sum++;}}
这里放上一组实验样例来供各位测试。
输入样例
3
4 A B C D
2
A B
A C
6 V1 V2 V3 V4 V5 V6
5
V1 V2
V1 V3
V2 V4
V5 V6
V3 V5
8 1 2 3 4 5 6 7 8
5
1 2
1 3
5 6
5 7
4 8
输出样例
A B C D
0 1 1 0
1 0 0 0
1 0 0 0
0 0 0 0
2
V1 V2 V3 V4 V5 V6
0 1 1 0 0 0
1 0 0 1 0 0
1 0 0 0 1 0
0 1 0 0 0 0
0 0 1 0 0 1
0 0 0 0 1 0
1
1 2 3 4 5 6 7 8
0 1 1 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 1 0
0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 0
3
以下是代码
#include <iostream>
#include <queue>
using namespace std;
int sum = 0;class Node
{
public:int pos;string data;Node* next;Node() { data = "-";pos = 0;next = NULL; }
};
class List
{
public:Node* head;List() { head = new Node(); }void Init(int n);void Show();void GetSide(int**mat);int GetPos(string a);
};
void List::Init(int n)
{Node* end = head;for (int i = 1;i <= n;i++){Node* tmp = new Node();cin >> tmp->data;tmp->pos = i;end->next = tmp;end = end->next;}
}
void List::Show()
{Node* end = head->next;while (end){if (end->next == NULL){cout << end->data;}else{cout << end->data << " ";}end = end->next;}cout << endl;
}
void List::GetSide(int**mat)
{int side;cin >> side;for (int i = 0;i < side;i++){string a, b;cin >> a >> b;int pos, pos2;pos = GetPos(a);pos2 = GetPos(b);mat[pos-1][pos2-1] = 1;mat[pos2-1][pos-1] = 1;}
}
int List::GetPos(string a)
{Node* end = head->next;while (end){if (end->data == a){return end->pos;}end = end->next;}return -1;
}void BFS(int x,int n,int**mat,int*visit)
{queue<int>Q;Q.push(x);visit[x] = 1;while (!Q.empty()){int cur = Q.front();Q.pop();for (int i = 0;i < n;i++){if (visit[i]==0 && mat[cur][i]){visit[i] = 1;Q.push(i);}}}
}
void InitMat(int** mat, int n)
{for (int i = 0;i < n;i++){for (int j = 0;j < n;j++){mat[j] = new int[n];mat[i][j] = 0;}}for (int i = 0;i < n;i++){for (int j = 0;j < n;j++){mat[i][j] = 0;}}
}
void DeleteMat(int** mat, int n)
{for (int i = 0;i < n;i++){for (int j = 0;j < n;j++){if (j == n - 1){cout << mat[i][j];}else{cout << mat[i][j] << " ";}}cout << endl;}for (int i = 0;i < n;i++){delete[]mat[i];}delete[]mat;
}
int main()
{int t;cin >> t;while (t--){sum = 0;int n;cin >> n;int** mat = new int* [n];InitMat(mat, n);List list;list.Init(n);list.GetSide(mat);int* visit = new int[n];for (int i = 0;i < n;i++){visit[i] = 0;}for (int i = 0;i < n;i++){if (visit[i] == 0){BFS(i,n,mat,visit);sum++;}}list.Show();DeleteMat(mat, n);cout << sum << endl;cout << endl;delete[]visit;}
}
C++通过邻接矩阵求连通分量(BFS)相关推荐
- 【dfs】【bfs】【链表】 求连通分量 (ssl 1759)
求连通分量 ssl 1759 题目大意 由n个点组成的无向图,求连通在一起的点数最大是多少 原题 求一个图的连通分量 Input n 顶点数(<=100) 边 Output 连通分量 Sampl ...
- 求连通分量(DFS)(BFS)(STL)
文章目录 求连通分量 1.深搜(邻接矩阵) 2.深搜(邻接表) 3.广搜(邻接矩阵) 4.广搜(邻接表) 5.STL(邻接表) 谢谢欣赏 求连通分量 Description 求一个图的连通分量 Inp ...
- 2015多校10 1006.CRB and Puzzle HDU5411(邻接矩阵求k长路条数,矩阵快速幂
题意:有若干字符,现在要把它们连成一个字符串,每种字符后面只能接特定种类的字符,现在询问能连接出的长度小于等于m的字符串有多少种. 思路:我们可以把这个转移关系看成一个图,如果字符a后面可以接b,那么 ...
- 邻接矩阵/图/DFS/BFS
目录 1.邻接矩阵的表示 2.邻接矩阵的存储 3.采用邻接矩阵表示法创建无向网 4.基于邻接矩阵的图上各类操作 5.DFS 6.BFS 7.测试程序(待完成) 权与网 连通分量(强连通分量) 1.邻接 ...
- G - Strongly connected - hdu 4635(求连通分量)
题意:给你一个图,问最多能添加多少条边使图仍为不是强连通图,如果原图是强连通输出 '-1' 分析:先把求出连通分量进行缩点,因为是求最多的添加边,所以可以看成两部分 x,y,只能一部分向另外一部分连边 ...
- 求最短路径——BFS、Dijkstra、Prim算法对比
来自王道数据结构
- 用邻接矩阵求无向图的连同分支数
大神:http://blog.csdn.net/esonjohn/article/details/52403185
- java判断图中两点是否连通_连通分量(求有几个连通分量+判断是否两点连通+是否为强联通图 相应例子)...
参考博客: https://blog.csdn.net/jinzk123/article/details/52231527 https://blog.csdn.net/qq_40998706/arti ...
- Maze Problem(求最短距离)BFS
题目链接: http://openoj.awaysoft.com/JudgeOnline/problem.php?id=1107 不多说,求最短距离~BFS 1 #include<stdio.h ...
最新文章
- 数据库创建索引的原则
- php字符串替换多余逗号_PHP字符过滤函数去除字符串最后一个逗号(rtrim)
- 示波器触发模式及其使用
- python开源代码-mtcnn python 开源代码详细图解
- Java集合:数组的使用
- 3、Python 基础类型 -- List 列表类型
- linux 用mutex定义一个linkedlist,【基于LINUX的操作系统实验教程最终版材料】
- python基础——使用模块
- 北大青鸟c语言课后答案,北大青鸟C语言教程--第一章 C语言基础.ppt
- 论文页眉奇偶页不同怎么设置_怎样设置Word页眉页脚奇偶页不同?
- linux 取消nologin_Linux中nologin的应用 转
- Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案
- getchar() 和 scanf(%c)的区别
- unity下载和安装
- 「软件项目管理」一文详解软件项目进度计划
- 电脑配置PC2022年版(4000元左右)详细配置表——(专业数据)
- java是先学前端还是后端_我应该学前端还是后端?
- Python项目实战化:爬取堆糖网研究所美好生活照
- Idea启动文件配置java目录_项目IDEA启动配置
- 切换窗口快捷键 你知道吗?
热门文章
- datahub文档_DataHub使用指南-阿里云开发者社区
- 排序算法算法之Bubble Sort
- 网页中在线玩合金弹头
- android 制作系统程序,教你制作定制版安卓系统(Android ROM)
- 浙大远程计算机基础知识题库,浙大远程教育1.计算机基础知识题答卷.docx
- Word快速更改文字大小写(转)
- 【网页设计】基于HTML在线图书商城购物项目设计与实现----(图书商城 7页 带登录注册)
- iis服务器突然网站访问不了了,iis6 无法访问网站_IIS重启无效(重启服务器才正常 Connections_Refused引起)...
- oracle ping 超时_Oracle连接错误解决方法(TNS-12535: TNS: 操作超时)
- 课后作业:情境三:程序结构与数组 1、分支