并查集
板子
第一部分:赋值
void init()
{
for(int i=0; i<=MAX; i++)
{
father[i] = i;
}
}
第二部分:找爹
int getf(int x)
{
if(father[x] != x)
{
father[x] = getf(father[x]);
}
return father[x];
}
int getf(int x)
{
if(father[x] != x)
{
int t = father[x];
father[x] = getf(father[x]);
value[x] += value[t];
}
return father[x];
}
第三部分:联合,找环
void _unite(int x,int y)
{
x = find(x);
y = find[y];
if(x == y)
{
return 0;
}
else
{
father[x] = y;
return 1;
}
}
第四部分:板子
HDU_1213 How Many Tables
# include <bits/stdc++.h>
using namespace std;
const int MAX = 1e6 + 6;
int father[MAX];
void init()
{
for(int i=0; i<=MAX; i++)
{
father[i] = i;
}
}
int getf(int x)
{
if(father[x] == x)
{
return x;
}
else
{
father[x] = getf(father[x]);
return father[x];
}
}
int _unite(int x,int y)//这个函数得作用还可以判断环
{
x = getf(x);
y = getf(y);
if(x == y)
{
return 0;
}
else
{
father[x] = y;
return 1;
}
}
int main (void)
{
int T;
cin>>T;
while(T--)
{
init();//赋值,初始化
int n, m;
cin>>n>>m;
for(int i=0; i<m; i++)
{
int x,y;
cin>>x>>y;
_unite(x, y);
}
int ans = 0;
for(int i=1; i<=n; i++)
{
if(father[i] == i)
ans++;
}
cout<<ans<<endl;
}
}
优化
避免树太长:
为了避免树太长,设一个代表树长的数组_rank[MAX],当两个元素结合的时候(前提不是环),将树小的一方变成子字节。
# include <bits/stdc++.h>
using namespace std;
const int MAX = 1e6 + 6;
int father[MAX];
int _rank[MAX];
void init()
{
for(int i=0; i<=MAX; i++)
{
_rank[i] = 0;
father[i] = i;
}
}
int getf(int x)
{
if(father[x] == x)
{
return x;
}
else
{
father[x] = getf(father[x]);
return father[x];
}
}
int _unite(int x,int y)//这个函数得作用还可以判断环
{
x = getf(x);
y = getf(y);
if(x == y)
{
return 0;
}
else
{
if(_rank[x] > _rank[y])
father[y] = x;
else if(_rank[x] < _rank[y])
father[x] = y;
else if(_rank[y] == _rank[x])
{
father[x] = y;
_rank[y]++;//注意_rank里面是y,y是父节点
}
return 1;
}
}
int main (void)
{
int T;
cin>>T;
while(T--)
{
init();//赋值,初始化
int n, m;
cin>>n>>m;
for(int i=0; i<m; i++)
{
int x,y;
cin>>x>>y;
_unite(x, y);
}
int ans = 0;
for(int i=1; i<=n; i++)
{
if(father[i] == i)
ans++;
}
cout<<ans<<endl;
}
}