并查集(Union Find)
并查集(Union Find)
准备工作
可以先看这个 超有爱的并查集~
解释的非常生动形象 tql
正文
oj用的是洛谷 P3367 【模板】并查集
优化有两种方式:
- 路径压缩(常用)
- 按秩合并
路径压缩
#include <bits/stdc++.h> using namespace std; int n,m; int pre[10005]; //父节点 int find(int r){ if(r==pre[r]) return r; //根节点的pre是自己 return pre[r]=find(pre[r]); //①路径压缩 } int main(){ cin>>n>>m; for(int i=0;i<=n;++i) pre[i]=i; int zi,xi,yi,r1,r2; while(m--){ cin>>zi>>xi>>yi; r1=find(xi); r2=find(yi); if(zi==1){ //普通合并 if(r1!=r2) pre[r1]=r2; //xi所在的树合并到yi所在树 } else{ //判断是否在一个并查集 if(r1!=r2) cout<<"N\n"; else cout<<"Y\n"; } } return 0; }
按秩合并
#include <bits/stdc++.h> using namespace std; int n,m; int pre[10005]; //父节点 int ran[10005]; //秩(树高) int find(int r){ if(r==pre[r]) return r; return pre[r]=find(pre[r]); //①路径压缩 } int main(){ cin>>n>>m; for(int i=0;i<=n;++i) {pre[i]=i; ran[i]=1;} int zi,xi,yi,r1,r2; while(m--){ cin>>zi>>xi>>yi; r1=find(xi); r2=find(yi); if(zi==1){ //②按秩合并 if(r1!=r2){ //将高度小的树合并到高度大的树上 if(ran[r1]<ran[r2]) //r1->r2 pre[r1]=r2; else{ //r2->r1 if(ran[r1]==ran[r2]) ++ran[r1]; //相等合并时树高+1 pre[r2]=r1; } } } else{ if(r1!=r2) cout<<"N\n"; else cout<<"Y\n"; } } return 0; }
原文地址:https://www.cnblogs.com/lidasu/p/10943995.html
相关推荐
-
命名管道的阻塞和非阻塞模式的初步探讨 c/c++
2019-3-30
-
pcl常用小知识 c/c++
2019-3-29
-
c/c++中的“大小,长度”问题 c/c++
2019-3-30
-
C++ Primer 第二章 学习笔记及习题答案 c/c++
2019-3-28
-
C++ 线程安全的单例模式总结 c/c++
2019-9-1
-
深入理解计算机系统读书笔记 c/c++
2019-3-29
-
栈的三种实现 c/c++
2019-3-30
-
文本搜索(C实现) c/c++
2019-3-30
-
如何写好C代码之依赖注入 c/c++
2019-4-5
-
const无处不在! c/c++
2019-3-28