在求图的连通分量时可能会碰见的问题--已经构造出了邻接矩阵,但不知道怎么求连通分量。这里选择用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)相关推荐

  1. 【dfs】【bfs】【链表】 求连通分量 (ssl 1759)

    求连通分量 ssl 1759 题目大意 由n个点组成的无向图,求连通在一起的点数最大是多少 原题 求一个图的连通分量 Input n 顶点数(<=100) 边 Output 连通分量 Sampl ...

  2. 求连通分量(DFS)(BFS)(STL)

    文章目录 求连通分量 1.深搜(邻接矩阵) 2.深搜(邻接表) 3.广搜(邻接矩阵) 4.广搜(邻接表) 5.STL(邻接表) 谢谢欣赏 求连通分量 Description 求一个图的连通分量 Inp ...

  3. 2015多校10 1006.CRB and Puzzle HDU5411(邻接矩阵求k长路条数,矩阵快速幂

    题意:有若干字符,现在要把它们连成一个字符串,每种字符后面只能接特定种类的字符,现在询问能连接出的长度小于等于m的字符串有多少种. 思路:我们可以把这个转移关系看成一个图,如果字符a后面可以接b,那么 ...

  4. 邻接矩阵/图/DFS/BFS

    目录 1.邻接矩阵的表示 2.邻接矩阵的存储 3.采用邻接矩阵表示法创建无向网 4.基于邻接矩阵的图上各类操作 5.DFS 6.BFS 7.测试程序(待完成) 权与网 连通分量(强连通分量) 1.邻接 ...

  5. G - Strongly connected - hdu 4635(求连通分量)

    题意:给你一个图,问最多能添加多少条边使图仍为不是强连通图,如果原图是强连通输出 '-1' 分析:先把求出连通分量进行缩点,因为是求最多的添加边,所以可以看成两部分 x,y,只能一部分向另外一部分连边 ...

  6. 求最短路径——BFS、Dijkstra、Prim算法对比

    来自王道数据结构

  7. 用邻接矩阵求无向图的连同分支数

    大神:http://blog.csdn.net/esonjohn/article/details/52403185

  8. java判断图中两点是否连通_连通分量(求有几个连通分量+判断是否两点连通+是否为强联通图 相应例子)...

    参考博客: https://blog.csdn.net/jinzk123/article/details/52231527 https://blog.csdn.net/qq_40998706/arti ...

  9. Maze Problem(求最短距离)BFS

    题目链接: http://openoj.awaysoft.com/JudgeOnline/problem.php?id=1107 不多说,求最短距离~BFS 1 #include<stdio.h ...

最新文章

  1. 数据库创建索引的原则
  2. php字符串替换多余逗号_PHP字符过滤函数去除字符串最后一个逗号(rtrim)
  3. 示波器触发模式及其使用
  4. python开源代码-mtcnn python 开源代码详细图解
  5. Java集合:数组的使用
  6. 3、Python 基础类型 -- List 列表类型
  7. linux 用mutex定义一个linkedlist,【基于LINUX的操作系统实验教程最终版材料】
  8. python基础——使用模块
  9. 北大青鸟c语言课后答案,北大青鸟C语言教程--第一章 C语言基础.ppt
  10. 论文页眉奇偶页不同怎么设置_怎样设置Word页眉页脚奇偶页不同?
  11. linux 取消nologin_Linux中nologin的应用 转
  12. Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案
  13. getchar() 和 scanf(%c)的区别
  14. unity下载和安装
  15. 「软件项目管理」一文详解软件项目进度计划
  16. 电脑配置PC2022年版(4000元左右)详细配置表——(专业数据)
  17. java是先学前端还是后端_我应该学前端还是后端?
  18. Python项目实战化:爬取堆糖网研究所美好生活照
  19. Idea启动文件配置java目录_项目IDEA启动配置
  20. 切换窗口快捷键 你知道吗?

热门文章

  1. datahub文档_DataHub使用指南-阿里云开发者社区
  2. 排序算法算法之Bubble Sort
  3. 网页中在线玩合金弹头
  4. android 制作系统程序,教你制作定制版安卓系统(Android ROM)
  5. 浙大远程计算机基础知识题库,浙大远程教育1.计算机基础知识题答卷.docx
  6. Word快速更改文字大小写(转)
  7. 【网页设计】基于HTML在线图书商城购物项目设计与实现----(图书商城 7页 带登录注册)
  8. iis服务器突然网站访问不了了,iis6 无法访问网站_IIS重启无效(重启服务器才正常 Connections_Refused引起)...
  9. oracle ping 超时_Oracle连接错误解决方法(TNS-12535: TNS: 操作超时)
  10. 课后作业:情境三:程序结构与数组 1、分支