分别利用并查集,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 ...
随机推荐
- Java学习 · 初识 容器和数据结构
容器和数据结构 1. 集合的引入 a) 集合的使用场景:需要将一些相同结构的个体整合到一起时 i. 新闻列表 ii. 邮件列表 iii. ...
- POJ 3046
题目大意:蚂蚁牙黑,蚂蚁牙红:有A只蚂蚁,来自T个家族,分别记为ant[i]个.同一个家族的蚂蚁长得一样,但是不同家族的蚂蚁牙齿颜色不同.任取n只蚂蚁(S <= n <= B),求能组成几 ...
- 【第三章】MySQL数据库的字段约束:数据完整性、主键、外键、非空、默认值、自增、唯一性
一.表完整性约束 作用:用于保证数据的完整性和一致性==============================================================约束条件 说明PRIM ...
- 剑指offer-从上往下打印二叉树22
题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. class Solution: # 返回从上到下每个节点值列表,例:[1,2,3] def PrintFromTopToBottom( ...
- 线性代数之——微分方程和 exp(At)
本节的核心是将常系数微分方程转化为线性代数问题. \[\frac{du}{dt}=\lambda u \quad 的解为 \quad u(t) = Ce^{\lambda t}\] 代入 \(t=0\ ...
- usb_modeswitch移植
usb_modeswitch移植 交叉工具链安装 交叉编译安装libsub库 交叉编译安装lib-compat-x.x.x 交叉编译安装usb_modeswitch 交叉编译工具链 为了使编译的程序可 ...
- Ubuntu14.04下部署FastDFS 5.08+Nginx 1.9.14
最新的版本可以在这里获取,目前下载的最新版本是5.08,更新于2016-02-03.在这里可以找到更多的说明. 下载好后,server端分为两个部分,一个是tracker,一个是storage.顾 ...
- 软件工程第二周PSP
- Thunder团队第六周 - Scrum会议1
Scrum会议1 小组名称:Thunder 项目名称:i阅app Scrum Master:王航 工作照片: 参会成员: 王航(Master):http://www.cnblogs.com/wangh ...
- 让我们一起来做最漂亮的Android界面吧!
让我们一起来做最漂亮的Android界面吧! AndroidiOS产品设计 摘要:如何为Android设备量身定制以打造出最为完美的应用?这是让诸多开发者很是头疼的问题.不同于iOS,Android设 ...