判断无向图是否联通模板(并查集版)(DFS),BFS等其他方法将陆续更新
所谓并查集一般是两个功能,当然其他的拓展一下即可
功能一,并,就是指把两颗树并在一起
功能二,查,就是查找这个节点的根节点(根节点的根节点就是本身)
emmmm对于判断我们不需要用到并的功能,因为,,,都并到一起了,还分个球的不通
/* 这种解法是因为若一个无向图是联通的那么任意两个点就是连着的 则可以把他们看成一棵树,只是看成而已,因为会有环 如果都是联通的,那么则会只有一个根,如果有多个根则说明不是联通图 */ #include"pch.h" #include<stdio.h> #include<iostream> #include <queue> #include<cmath> #define mem(a,b) memset(a,b,sizeof a); #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn = 1010; int n, m; int pre[maxn];//存其根节点的序号 //初始化,让其本身为其根 void init() { for (int i = 1; i <= n; i++) pre[i] = i; } //寻找该节点的根节点 int find(int x) { return pre[x] == x ? x : pre[x] = find(pre[x]); } int main() { while (~scanf_s("%d%d", &n, &m)) { init(); int u, v; for (int i = 0; i < m; i++) { scanf_s("%d%d", &u, &v); pre[find(u)] = pre[find(v)]; // 合并为同一个根 } int cnt = 0; for (int i = 1; i <= n; i++) // 统计 root 结点个数 if (pre[i] == i) { cnt++; if (cnt > 1) break; } puts(cnt == 1 ? "YES" : "NO"); } return 0; }
接下来是用DFS算法的解法
首先我们了解一下什么是DFS
深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。
沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。
这一过程一直进行到已发现从源节点可达的所有节点为止。
如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,
整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。
简称不撞南墙不回头
深度优先遍历的主要思想就是:首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;
当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问。
沿着某条路径遍历直到末端,然后回溯,再沿着另一条进行同样的遍历,直到所有的顶点都被访问过为止。
所以这里我们可以对每个顶点进行DFS,如果能一次遍历所有顶点则是联通的,反之则不是联通的
/* DFS解法 by tp */ #include<cstdio> #include<cstring> using namespace std; const int maxn = 100; int p[maxn][maxn];//这里在数据范围小的时候使用邻接矩阵会简单方便很多 int known[maxn];//这里是存放该节点是否被访问过的判断 int v, e;//顶点数,遍数 void DFS(int s) { for (int u = 0; u < v; u++) { if (!known[u] && p[s][u])//只有没访问过的且联通的点才进行访问 { known[u] = 1; //访问过的点进行标记 DFS(u); } } return; } int main() { while (scanf("%d%d", &v, &e) != EOF) { memset(p, 0, sizeof(p)); memset(known, 0, sizeof(known)); int s, t; for (int i = 0; i < e; i++) { scanf("%d%d", &s, &t); p[s][t] = 1; p[t][s] = 1; } int count = 0; for (int i = 0; i < v; i++) { if (!known[i]) { DFS(i); count++; } } if (count == 1)//如果是联通的图,那么在一次DFS在就会全标记上,所以count只会加一次 { printf("是连通图\n"); } else { printf("不是连通图,count=%d\n", count); } } return 0; }