数据结构实验:连通分量个数

来源:互联网 发布:生物大数据 精准医疗 编辑:程序博客网 时间:2024/06/09 17:42

题目描述

 在无向图中,如果从顶点vi到顶点vj有路径,则称vi和vj连通。如果图中任意两个顶点之间都连通,则称该图为连通图,
否则,称该图为非连通图,则其中的极大连通子图称为连通分量,这里所谓的极大是指子图中包含的顶点个数极大。
例如:一个无向图有5个顶点,1-3-5是连通的,2是连通的,4是连通的,则这个无向图有3个连通分量。
 

输入

 第一行是一个整数T,表示有T组测试样例(0 < T <= 50)。每个测试样例开始一行包括两个整数N,M,(0 < N <= 20,0 <= M <= 200)
分别代表N个顶点,和M条边。下面的M行,每行有两个整数u,v,顶点u和顶点v相连。

输出

 每行一个整数,连通分量个数。

示例输入

23 11 23 23 21 2

示例输出

21

提示



#include <iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef struct arcnode
{
    int adj;
}arcnode,adjmatrix[200][200];
typedef struct
{
    adjmatrix a;
    int vn;
    int an;
}MG;
int create(MG &g,int n,int m)//生成邻接矩阵;
{
    int i,j;
    int v1,v2;
    g.vn=n;
    g.an=m;
    for(i=1;i<=g.vn;i++)
        for(j=1;j<=g.vn;j++)
         g.a[i][j].adj=0;
    for(i=1;i<=g.an;i++)
    {
        scanf("%d%d",&v1,&v2);
        g.a[v1][v2].adj=1;
        g.a[v2][v1]=g.a[v1][v2];
    }
    return 1;
}
int v[110];//标记图的顶点是否访问过;
void dfs(MG &g,int i)//深度优先搜索;
{
    int j;//j在函数内部,不然不能回溯;
    v[i]=1;
    for(j=1;j<=g.vn;j++)
        if(g.a[i][j].adj==1&&!v[j])
    {
        dfs(g,j);
    }
}
int i,count;//记录连通分量个数;
void dfs1(MG &g)//统计连通分量的个数
{
    //int i;//若不在函数内部不会回溯;
    for(i=1;i<=g.vn;i++)
        if(!v[i])
    {
        count++;
        dfs(g,i);
    }
}
int main()
{
    int t;
    MG g;
    scanf("%d",&t);
    while(t--)
    {
        count=0;
        memset(v,0,sizeof(v));//标记数组初始化;
        int n,m;
        scanf("%d%d",&n,&m);
        create(g,n,m);
        dfs1(g);
        printf("%d\n",count);
    }
    return 0;
}



#include <cstdio>#define MAX 2000using namespace std;int pre[MAX+1];void Initialize(int n) {// 初始化各结点的 pre 为自身for(int i=0; i<=n; ++i) {// 相当于初始时每个结点为各自独立的集合pre[i] = i;}}int Find(int a) {// 查找 a 所在集合的根结点 rootint root = a;// root 初始化为其本身while(pre[root] != root) {// 当 root 的上级结点不是其本身root = pre[root];// 令 root 为它的上级结点,继续查找}while(pre[a] != root) {// 再次遍历,路径压缩int temp = pre[a];pre[a] = root;// 沿途结点直接指向到 roota = temp;}return root;}void Join(int a, int b) {// 将 a, b 结点所在的集合合并int root_a = Find(a);// 查找 a 所在集合的根结点int root_b = Find(b);// 查找 b 所在集合的根结点if(root_a != root_b) {// 如果 a, b 不在同一集合,则合并if(root_a > root_b)// 根结点下标大的集合并入下标小的集合pre[root_a] = root_b;else pre[root_b] = root_a;}}int Count(int n) {// 统计不相交集合的个数int cnt = 0;// 计数变量for(int i=1; i<=n; ++i) {int root = Find(i);// 找到一个集合if(root) {// 如果是第一次找到此集合cnt++;// 计数pre[root] = 0;// 此根节点置0,防止重复}}return cnt;}int main(int argc, char const *argv[]) {int t, n, m, u, v;scanf("%d", &t);while(t--) {scanf("%d %d", &n, &m);Initialize(n);while(m--) {scanf("%d %d", &u, &v);Join(u, v);}printf("%d\n", Count(n));}return 0;}

0 0
原创粉丝点击