并查集模板hdu-1213
时间:2019-09-14
本文章向大家介绍并查集模板hdu-1213,主要包括并查集模板hdu-1213使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
例题:hdu 1213
//#include <bits/stdc++.h>
#include <iostream>
#include <stack>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <list>
#include <map>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAXN = 1005;
int s[MAXN];
void init_set(){
for(int i = 1; i <= MAXN; i++)
s[i] = i;
}
int find_set(int x){
return x = s[x]? x: find_set(s[x]);
}
void union_set(int x, int y){
x = find_set(x);
y = find_set(y);
if(x != y) s[x] = s[y];
}
int main(){
int t, n, m, x, y;
cin >> t;
while(t--){
cin >> n >> m;
init_set();
for(int i = 1; i <= m; i++){
cin >> x >> y;
union_set(x, y);
}
int ans = 0;
for(int i = 1; i <= n; i++){
if(s[i] == i) ans++;
}
cout << ans << endl;
}
return 0;
}
在上述程序中,find_set()、union_set()的搜索深度都是O(n),性能较差,下面进行优化,优化之后查找和合并的复杂度都是O(logn)。
1、合并的优化
在合并x 和 y时先搜到他们的根节点,然后再合并这两个根节点,即把一个根节点的集改成另一个根节点。这连个根节点的高度不同,如果把高度较小的那一个合并到较大的集上,能减小树的高度。下面是优化后的代码,再初始化时有height[i],定义元素i的高度。
int height[MAXN];
void init_set(){
for(int i = 1; i <= MAXN; i++){
s[i] = i;
height[i] = 0;
}
}
void union_set(int x, int y){
x = find_set(x);
y = find_set(y);
if(height[x] == height[y]){
height[x] = height[x] + 1;
s[y] = x;
}
else{
if(height[x] < height[y]) s[x] = y;
else s[y] = x;
}
}
2、查询的优化——路径的压缩
在上面的查询程序 find_set()中,查询元素 i 所属的集合需要搜索路径找到根节点,返回的结果也是根节点。这条路径可能很长。如果在返回的时候顺便把 i 所属的集改成根节点,那么下次搜索的时候在 O(1) 的时间内就能得到结果。
程序如下:
int find_set(int x){
if(x != s[x])
s[x] = find_set(s[x]);
return s[x];
}
上面的代码用递归实现,如果数据规模太大,担心爆栈,可以用下面的非递归代码。
int find_set(int x){
int r = x;
while(s[r] != r) //找到根节点
r = s[r];
int i = x, j;
while(i != r){
j = s[i];
s[i] = r;
i = j;
}
return r;
}
3、优化完成的代码
//#include <bits/stdc++.h>
#include <iostream>
#include <stack>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <list>
#include <map>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAXN = 1005;
int s[MAXN];
int height[MAXN];
void init_set(){
for(int i = 1; i <= MAXN; i++){
s[i] = i;
height[i] = 0;
}
}
int find_set(int x){
int r = x;
while(s[r] != r) //找到根节点
r = s[r];
int i = x, j;
while(i != r){
j = s[i];
s[i] = r;
i = j;
}
return r;
}
void union_set(int x, int y){
x = find_set(x);
y = find_set(y);
if(height[x] == height[y]){
height[x] = height[x] + 1;
s[y] = x;
}
else{
if(height[x] < height[y]) s[x] = y;
else s[y] = x;
}
}
int main(){
int t, n, m, x, y;
cin >> t;
while(t--){
cin >> n >> m;
init_set();
for(int i = 1; i <= m; i++){
cin >> x >> y;
union_set(x, y);
}
int ans = 0;
for(int i = 1; i <= n; i++){
if(s[i] == i) ans++;
}
cout << ans << endl;
}
return 0;
}
原文地址:https://www.cnblogs.com/lihello/p/11520738.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android开发之全屏与非全屏的切换设置方法小结
- Android使用GridView实现日历的方法
- Android控件AppWidgetProvider使用方法详解
- R语言使用链梯法Chain Ladder和泊松定律模拟和预测未来赔款数据
- Android ViewPager实现左右滑动的实例
- R语言通过伽玛与对数正态分布假设下的广义线性模型对大额索赔进行评估预测
- R语言中回归模型预测的不同类型置信区间应用比较分析
- 第06期:Prometheus 存储
- 新特性解读 | 数组范围遍历功能
- 技术分享 | MySQL 内存管理初探
- 新特性解读 | 窗口函数的适用场景
- Android自定义View 仿QQ侧滑菜单的实现代码
- Android view随触碰滑动效果
- TextView使用SpannableString设置复合文本 SpannableString实现TextView的链接效果
- FragmentTabHost使用方法详解