HDU 1232 并查集/dfs

时间:2021-11-12 04:10:28

原题:

http://acm.hdu.edu.cn/showproblem.php?pid=1232

我的第一道并查集题目,刚刚学会,我是照着《啊哈算法》这本书学会的,感觉非常通俗易懂,另外还有一篇同样非常好的博客:http://blog.csdn.net/niushuai666/article/details/6662911

这两位大神已经把并查集讲解的非常透彻了,所以我就不班门弄斧了。。。

刚开始看到这道题的时候,我并不知道这里是怎么用到并查集的,可以说我对并查集的理解还不是很到位。看了上面那篇博文后才算有点明白了,并查集的本质就是维护一个森林,适合来解决一个图有几个连通分支的问题。

我刚开始是用深度优先搜索做的,和并查集的本质其实是一样的,就是先存储整个图,然后对每个节点进行深度优先搜索,这个每一次的搜索过程,就是对这个节点所扩展出的独立分支就行遍历,把所到之处的每一个节点进行标记,好下次不再访问已经访问过的节点。最后,我们统计总共进行深搜的次数,这就是对应着有几个独立的分支。当然,这个方法效率并不如并查集高,但也算是为大家提供了另一个思路吧(^_^)

深搜:

 #include<stdio.h>
#include<string.h>
#define maxn 1005
int map[maxn][maxn],book[maxn];//map用来存储图,book是标记每个点是否已经访问过
int n,m;
void dfs(int cur){//cur表示当前节点
for(int i = ;i<=n;i++){
if(book[i]==&&map[cur][i]==){
book[i] = ;
dfs(i);
}
}
}
int main(){
while(scanf("%d",&n)!=EOF&&n){
scanf("%d",&m);
memset(map,,sizeof(map));
memset(book,,sizeof(book));
for(int i = ;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
map[u][v] = ;
map[v][u] = ;
}
int sum = ;
for(int i = ;i<=n;i++){
if(book[i]==){
book[i] = ;//这句不要忘了,从当前节点开始搜索时,要标记
dfs(i);
sum++;
}
}
printf("%d\n",sum-);
}
return ;
}

我又用新学到的并查集来写了这道题(代码用了《啊哈算法》里的模板),算是一道非常好的并查集入门题吧~

 #include<stdio.h>
#define maxn 1005
int n,m;
int f[maxn];
int getf(int a){
if(f[a]==a){
return a;
}else{
f[a] = getf(f[a]);
return f[a];
}
}
//合并函数
void merge(int u,int v){
int t1 = getf(u);
int t2 = getf(v);
if(t1!=t2)
f[t2] = t1;
}
int main(){
while(scanf("%d",&n)!=EOF&&n){
scanf("%d",&m);
//初始化每个节点
for(int i = ;i<=n;i++)
f[i] = i;
for(int i = ;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
merge(u,v);
}
int sum = ;
for(int i = ;i<=n;i++)
if(f[i]==i)
sum++;
printf("%d\n",sum-);
}
return ;
}