分别利用并查集,DFS和BFS方法求联通块的数量
联通块是指给定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方法求联通块的数量的更多相关文章
- 【紫书】Oil Deposits UVA - 572 dfs求联通块
题意:给你一个地图,求联通块的数量. 题解: for(所有还未标记的‘@’点) 边dfs边在vis数组标记id,直到不能继续dfs. 输出id及可: ac代码: #define _CRT_SECURE ...
- POJ1291-并查集/dfs
并查集 题意:找出给定的这些话中是否有冲突.若没有则最多有多少句是对的. /* 思路:如果第x句说y是对的,则x,y必定是一起的,x+n,y+n是一起的:反之x,y+n//y,x+n是一起的. 利用并 ...
- hdu6200 mustedge mustedge mustedge (并查集+dfs序树状数组)
题意 给定一个n个点m条边无向图(n,m<=1e5) 支持两个操作 1.添加一条边 2.询问点u到点v的所有路径中必经边的条数 操作数<=1e5 分析 第一眼看起来像是要动态维护无向图的边 ...
- 第46届ICPC澳门站 K - Link-Cut Tree // 贪心 + 并查集 + DFS
原题链接:K-Link-Cut Tree_第46屆ICPC 東亞洲區域賽(澳門)(正式賽) (nowcoder.com) 题意: 要求一个边权值总和最小的环,并从小到大输出边权值(2的次幂):若不存在 ...
- 【并查集缩点+tarjan无向图求桥】Where are you @牛客练习赛32 D
目录 [并查集缩点+tarjan无向图求桥]Where are you @牛客练习赛32 D PROBLEM SOLUTION CODE [并查集缩点+tarjan无向图求桥]Where are yo ...
- 利用DFS求联通块个数
/*572 - Oil Deposits ---DFS求联通块个数:从每个@出发遍历它周围的@.每次访问一个格子就给它一个联通编号,在访问之前,先检查他是否 ---已有编号,从而避免了一个格子重复访问 ...
- HDU 1232 并查集/dfs
原题: http://acm.hdu.edu.cn/showproblem.php?pid=1232 我的第一道并查集题目,刚刚学会,我是照着<啊哈算法>这本书学会的,感觉非常通俗易懂,另 ...
- 1021.Deepest Root (并查集+DFS树的深度)
A graph which is connected and acyclic can be considered a tree. The height of the tree depends on t ...
- POJ 1562 Oil Deposits (并查集 OR DFS求联通块)
Oil Deposits Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14628 Accepted: 7972 Des ...
随机推荐
- Hbase restFul API
获取hbase版本 curl -vi -X GET -H "Accept: text/xml" http://10.8.4.46:20550/version/cluster1.2. ...
- 改maven下创建的动态网站依赖的jre版本
问题描述 通过maven创建一个动态网站后,eclipse会提示一个提醒 Build path specifies execution environment J2SE-1.5. There are ...
- Mybatis中resultMap与resultType区别
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultM ...
- 适合初学者的嵌入式Linux计划
俗话说万事开头难,刚开始的时候,你是否根本就不知如何开始,上网查资料被一堆堆新名词搞的找不到北,去图书馆看书也是找不到方向?又是arm,又是linux,又是uboot头都大了,不知道自己究竟从哪里开始 ...
- Scrum1
Scrum1 组员 任务分工 贡献 林泽宇 团队分工.撰写博客.修改完善需求规格说明书.整理代码规范 李涵 后端架构设计 尹海川 logo设计修改.数据库数据 郏敏杰 课堂展示.查阅资料.整理关键和难 ...
- 20145214实验五 Java网络编程及安全
20145214实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验步骤 我的结对伙伴是 20145219 宋歌,我负责的 ...
- LintCode-381.螺旋矩阵 II
螺旋矩阵 II 给你一个数n生成一个包含1-n^2的螺旋形矩阵 样例 n = 3 矩阵为 [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ] 标 ...
- jquery.validate 中文乱码解决方法
第一种.就是所说的引用jquery.validate.messages_cn.js 下载地址:http://files.cnblogs.com/files/pin ...
- php缓存技术——memcache常用函数详解
php缓存技术——memcache常用函数详解 2016-04-07 aileen PHP编程 Memcache函数库是在PECL(PHP Extension Community Library)中, ...
- 分享几个.Net计划任务组件
Quartz http://www.quartz-scheduler.net/ Hangfire http://hangfire.io/ Install-Package Hangfire 使用OWIN ...