联通块是指给定n个点,输入a,b(1<=a,b<=n),然后将a,b连接,凡是连接在一起的所有数就是一个联通块;

题意:第一行输入n,m,分别表示有n个数,有输入m对连接点,以下将要输入m行(输入数据到文件截止);

输出:第一行要求输出联通块的个数,并在第二行分别输出每个联通块中点的数量,每个数之间以一个空格隔开。

样例 1
5 3
1 4
2 5
3 5
输出:2
2 3
样列2

9 8
1 2
2 3
3 4
3 7
4 5
4 6
7 8
7 9
输出:

1
9

如果不明白的话可以画图试试,最多花半个小时,要是早这样不知道能省下多少个半小时呢;

此题可以利用并查集求解:
首先可以将N个点看成独立的联通块,然后每个每个独立的联通块都有一个节点,然后每次连接两个点,就将它们的节点加在一起;
代码如下:

 #include<iostream>
#include<cstring>
using namespace std;
const int maxn=;
int p[maxn];//作为每个独立的点
int sum[maxn];//每个节点下面连接的点
int find(int x)
{
if(x==p[x])return x;
return p[x]=find(p[x]);//压缩路径
}
int main()
{
int n,m;
while(cin>>n>>m)
{
if(n==)//如果没有数据那就直接按照格式输出零 ,一般不会有这种输入
{
cout<<<<endl<<<<endl;
continue;
}
for(int i=;i<=n;i++)//初始化,令每一个点成为独立的联通块
{
p[i]=i;
sum[i]=;//每个联通块中节点的个数为 1
} int a,b;
for(int i=;i<=m;i++)
{
cin>>a>>b;
int fa=find(a);//查找a的头节点
int fb=find(b);//查找b的头节点
if(fa!=fb)//如果头节点不同
{
p[fa]=fb;//将两个点合并
sum[fb]+=sum[fa];//并且使新头节点中的个数加上新连接的联通块所含节点的个数
}
}
int count=;
for(int i=;i<=n;i++)
{
if(p[i]==i)//计算联通块的数量
{
count++;
}
}
cout<<count<<endl;
int flag=;
for(int i=;i<=n;i++)
{
if(p[i]==i)
{
if(flag==)cout<<" ";
flag=;
cout<<sum[i];
}
}
cout<<endl;
}
return ;
}

这个题目利用DFS求解也可以。

要建立一个二维数据,将要连接点的点连在一起,并且用一个一位数据记录每个点是否被搜索过;

代码如下:

 #include<iostream>
#include<cstring>
using namespace std;
const int maxn=;
int map[maxn][maxn];
int vis[maxn];
int tot;
int n,m;
void dfs(int s)
{
tot++;
vis[s]=;
for(int i=;i<=n;i++)
if(!vis[i]&&map[s][i])//当从1到n都搜索一遍后 变会自动停止
{
dfs(i);
}
}
int main()
{
int now=;
int v,u;
while(cin>>n>>m)
{
tot=;
now=;
int sum[maxn];
memset(map,,sizeof(map));
memset(vis,,sizeof(vis));
for(int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
map[u][v]=map[v][u]=;
}
for(int i=;i<=n;i++)
{
if(vis[i]==)
{
tot=;
dfs(i);
sum[++now]=tot;
}
}
cout<<now<<endl;
for(int i=;i<=now;i++)
{
if(i>)cout<<" ";
cout<<sum[i];
}
cout<<endl;
}
return ;
} 利用BFS做也是比较方便的; 利用队栈保存每次搜索到的数据,并且在处理完成它的子节点后删除;同时利用一个数组记录是否拜访过它; #include <cstdio>
#include <cstring>
#include<iostream>
#include <queue>
using namespace std;
#define N 100
int n,m;
int map[N][N];
int mk[N];
int sum[N];
int total;
void bfs(int s)
{
queue <int> Q;
Q.push(s);
mk[s]=;
while(!Q.empty())
{
int u=Q.front();Q.pop();
total++;
for(int i=;i<=n;i++)
{
if(map[u][i]&&!mk[i])
{
mk[i]=;
Q.push(i);
}
}
}
}
int main()
{
int u,v;
int now=;
while(scanf("%d%d",&n,&m)==)
{
now=;
memset(map,,sizeof(map));
memset(mk,,sizeof(mk));
for(int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
map[u][v]=map[v][u]=;
}
for(int i=;i<=n;i++)
{if(mk[i]==)
{
total=;
bfs(i);
sum[++now]=total;
}
}
cout<<now<<endl;
for(int i=;i<=now;i++)
{
if(i>)cout<<" ";
cout<<sum[i];
}
cout<<endl;
}
return ;
}

以上三个方法,都是比较容易理解上手的,能够很好的提高做类似题目的能力;

分别利用并查集,DFS和BFS方法求联通块的数量的更多相关文章

  1. 【紫书】Oil Deposits UVA - 572 dfs求联通块

    题意:给你一个地图,求联通块的数量. 题解: for(所有还未标记的‘@’点) 边dfs边在vis数组标记id,直到不能继续dfs. 输出id及可: ac代码: #define _CRT_SECURE ...

  2. POJ1291-并查集/dfs

    并查集 题意:找出给定的这些话中是否有冲突.若没有则最多有多少句是对的. /* 思路:如果第x句说y是对的,则x,y必定是一起的,x+n,y+n是一起的:反之x,y+n//y,x+n是一起的. 利用并 ...

  3. hdu6200 mustedge mustedge mustedge (并查集+dfs序树状数组)

    题意 给定一个n个点m条边无向图(n,m<=1e5) 支持两个操作 1.添加一条边 2.询问点u到点v的所有路径中必经边的条数 操作数<=1e5 分析 第一眼看起来像是要动态维护无向图的边 ...

  4. 第46届ICPC澳门站 K - Link-Cut Tree // 贪心 + 并查集 + DFS

    原题链接:K-Link-Cut Tree_第46屆ICPC 東亞洲區域賽(澳門)(正式賽) (nowcoder.com) 题意: 要求一个边权值总和最小的环,并从小到大输出边权值(2的次幂):若不存在 ...

  5. 【并查集缩点+tarjan无向图求桥】Where are you @牛客练习赛32 D

    目录 [并查集缩点+tarjan无向图求桥]Where are you @牛客练习赛32 D PROBLEM SOLUTION CODE [并查集缩点+tarjan无向图求桥]Where are yo ...

  6. 利用DFS求联通块个数

    /*572 - Oil Deposits ---DFS求联通块个数:从每个@出发遍历它周围的@.每次访问一个格子就给它一个联通编号,在访问之前,先检查他是否 ---已有编号,从而避免了一个格子重复访问 ...

  7. HDU 1232 并查集/dfs

    原题: http://acm.hdu.edu.cn/showproblem.php?pid=1232 我的第一道并查集题目,刚刚学会,我是照着<啊哈算法>这本书学会的,感觉非常通俗易懂,另 ...

  8. 1021.Deepest Root (并查集+DFS树的深度)

    A graph which is connected and acyclic can be considered a tree. The height of the tree depends on t ...

  9. POJ 1562 Oil Deposits (并查集 OR DFS求联通块)

    Oil Deposits Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14628   Accepted: 7972 Des ...

随机推荐

  1. 学习笔记,99乘法表,嵌套while循环

    line = 0 #定义外循环初变量 while line < 9: #外循环判断语句 line += 1 #改变外循环初变量,避免陷入死循环 row = 0 #定义内循环初变量 while r ...

  2. lock+Condition

    关键字 synchronized+wait/notify/notifyAll可以实现等待/通知模式,类ReentrantLock可以实现同样的功能,但需要借助Condition对象.Condition ...

  3. 统计单词数:string函数使用

    题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给 ...

  4. Hadoop第二课:Hadoop集群环境配置

    一.Yum配置 1.检查Yum是否安装 rpm -qa|grep yum 2.修改yum源,我使用的是163的镜像源(http://mirrors.163.com/),根据自己的系统选择源, #进入目 ...

  5. leetcode个人题解——#19 Remove Nth Node From End of List

    思路:设置两个指针,其中第二个指针比第一个延迟n个元素,这样,当第二个指针遍历到指针尾部时,对第一个指针进行删除操作. 当然,这题要注意一些边界值,比如输入[1,2] n=2时如果按照思路走会指向未分 ...

  6. Pandas dataframe数据写入文件和数据库

    转自:http://www.dcharm.com/?p=584 Pandas是Python下一个开源数据分析的库,它提供的数据结构DataFrame极大的简化了数据分析过程中一些繁琐操作,DataFr ...

  7. BZOJ 3790 神奇项链 hash/后缀自动机+贪心

    Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色. 为了制作这个项链,小 H 购买了两个机器.第一个机器可 ...

  8. vue.js学习之 跨域请求代理与axios传参

    vue.js学习之 跨域请求代理与axios传参 一:跨域请求代理 1:打开config/index.js module.exports{ dev: { } } 在这里面找到proxyTable{}, ...

  9. 第一章 Java Web应用开发技术

    Java Web应用开发是基于JavaEE(JavaEnterprise Edition)框架的,而JavaEE是建立在Java平台上的企业级应用解决方案.JavaEES框架提供的Web开发技术主要支 ...

  10. TCP系列35—窗口管理&流控—9、紧急机制

    一.概述 我们在最开始介绍TCP头结构的时候,里面有个URG的标志位,还有一个Urgent Pointer的16bits字段.当URG标志位有效的时候,Urgent Poinert用来指示紧急数据的相 ...