![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#define _for(i,a,b) for(int i = (a);i < (b);i ++) const int maxn = 50003; int par[maxn]; //父亲 int high[maxn]; //树的高度 void init(int n) { _for(i,0,n) { par[i] = i; high[i] = 0; } } int find(int x) { return par[x] == x ? x : par[x] = find(par[x]); } void unite(int x,int y) { x = find(x);y = find(y); if(x==y) return ; if(high[x]<high[y]) par[x] = y; else { par[y] = x; if(high[x]==high[y]) high[x] ++; } } bool same(int x,int y) { return find(x) == find(y); }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#define _for(i,a,b) for(int i = (a);i < (b);i ++) const int maxn = 50003; int par[maxn]; //父亲 void init(int n) { _for(i,0,n) par[i] = i; } int find(int x) { return par[x] == x ? x : find(par[x]); } void unite(int x,int y) { x = find(x);y = find(y); if(x==y) return ; par[x] = y; } bool same(int x,int y) { return find(x) == find(y); }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <bits/stdc++.h> using namespace std; #define _for(i,a,b) for(int i = (a);i < (b);i ++) const int maxn = 50003; int par[maxn]; //父亲 int high[maxn]; //树的高度 int id[maxn]; //映射,里面装的是现在真正的序号 int idEnd; void init(int n) { idEnd = n; _for(i,0,n) { par[i] = id[i] = i; high[i] = 0; } } int find(int x) { return par[x] == x ? x : par[x] = find(par[x]); } void unite(int x,int y) { x = find(x);y = find(y); if(x==y) return ; if(high[x]<high[y]) par[x] = y; else { par[y] = x; if(high[x]==high[y]) high[x] ++; } } void del(int x) { id[x] = idEnd ++; high[id[x]] = 0; par[id[x]] = id[x]; } bool same(int x,int y) { return find(x) == find(y); } int main() { init(7); unite(id[1],id[4]); unite(id[2],id[4]); unite(id[3],id[4]); unite(id[4],id[5]); unite(id[6],id[5]); cout << same(id[4],id[5]) << endl; del(id[4]); cout << same(id[4],id[5]) << endl; cout << same(id[1],id[5]) << endl; cout << same(id[6],id[2]) << endl; return 0; }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
map<string,int> IDcache; vector<string> Stringcache; int ID(string s) { if(IDcache.count(s)) return IDcache[s]; Stringcache.push_back(s); return IDcache[s] = Stringcache.size()-1; }
种类并查集:POJ-1182,解题策略是并查集的每个集合内的元素都同真或同假,所以每个动物就有3种可能的状态,在A或在B或在C。当第i个动物属于集合A这一命题和第j个动物属于集合B这一命题在并查集的同一集合内时,若此时出现新命题,为第i个动物和第j个动物是在同一集合内,只需要看i属于A这一状态是否和j属于B或者j属于C在并查集同一集合内,如果在同一集合内,说明两命题同真或同假,那么很显然新命题就是错误的,这样就能判定新命题的真假。
主要思想是由于动物种类的不确定,所以只能以命题的形式将多个命题通过并查集连接起来,以判断命题的真假。
带权并查集:主要思想是将一个并查集内的每个集合中的每个元素赋予一个权值,这个权值的意义可以是多样的,比如他与根节点的关系,或者不使用路径压缩时以他为根的权值之和。要多用一个数组,其大小就是总元素个数,来表示各种权值。