判断无向图是否联通模板(并查集版)(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;
}

 

posted @ 2019-05-05 20:11  悲离  阅读(717)  评论(0编辑  收藏  举报