并查集模板
并查集:通过压缩路径使查找更加迅速快捷,在大数据量上效果更加明显
递归实现:
int par[max_n];
int Rank[max_n];
void init(int n) //初始化父元素
{
for(int i=0; i<n; i++)
{
par[i] = i;
Rank[i] = 0;
}
}
int find_par(int n) //寻找根节点
{
if(par[n] == n) return n;
return par[n] = find_par(par[n]);
}
void unit_par(int a, int b) //合并集合
{
a = find_par(a);
b = find_par(b);
if(a == b) return;
if(Rank[a] < Rank[b]) par[a] = b; //b 节点更高,将a集合链接到pb
else
{
par[b] = a;
if(Rank[a] == Rank[b]) Rank[a]++;
}
}
bool same(int a, int b) //判断是否属于同一集合
{
return find_par(a) == find_par(b);
}
循环实现:
int par[max_n];
int Rank[max_n];
void init(int n) //初始化父元素
{
for(int i=0; i<n; i++)
{
par[i] = i;
Rank[i] = 0;
}
}
void find_par(int n) //查找父节点
{
int nn = n;
while(par[n] != n)
{
n = par[n];
}
int x = nn;
while(par[nn] != n)
{
x = par[nn];
par[nn] = n;
nn = x;
}
}
void unit_par(int a, int b) //合并集合
{
a = find_par(a);
b = find_par(b);
if(a == b) return;
if(Rank[a] < Rank[b]) par[a] = b; //b 节点更高,将a集合链接到pb
else
{
par[b] = a;
if(Rank[a] == Rank[b]) Rank[a]++;
}
}
bool same(int a, int b) //判断是否属于同一集合
{
return find_par(a) == find_par(b);
}
变形应用:
#include <iostream>
#include <cstdio>
#include <map>
#include <string>
using namespace std;
map<string, string> par;
map<string, int> Rank;
string Find(string s)
{
if(par[s] == s) return s;
return par[s] = Find(par[s]);
}
void unit_par(string a, string b)
{
a = Find(a);
b = Find(b);
if(a == b) return;
else
{
if(Rank[a] > Rank[b]) par[b] = a;
else
{
par[a] = b;
if(Rank[a] == Rank[b]) Rank[b]++;
}
}
return;
}
bool same(string a, string b)
{
return Find(a) == Find(b);
}
int main()
{
int n, m, p;
scanf("%d%d%d", &n, &m, &p);
string s, ss;
while(n--)
{
cin >> s;
par[s] = s;
Rank[s] = 0;
}
while(m--)
{
cin >> s >> ss;
s = Find(s);
ss = Find(ss);
unit_par(s, ss);
}
while(p--)
{
cin >> s >> ss;
if(same(s,ss)) printf("safe\n");
else printf("cc cry\n");
}
return 0;
}