1. 问题描述:
有一个叫做“数码世界”奇异空间,在数码世界里生活着许许多多的数码宝贝,其中有些数码宝贝之间可能是好朋友,并且数码宝贝世界有两条不成文的规定:
第一,数码宝贝A和数码宝贝B是好朋友等价于数码宝贝B与数码宝贝A是好朋友
第二,如果数码宝贝A和数码宝贝C是好朋友,而数码宝贝B和数码宝贝C也是好朋友,那么A和B也是好朋友,现在给出这些数码宝贝中所有好朋友的信息,问:可以把这些数码宝贝分成多少组,满足每组中的任意两个数码宝贝都是好朋友,而且任意两组之间的数码宝贝都不是好朋友。
解决方案:
1)朴素写法
/**
1)朴素写法
*/
/**
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=110;
int a[maxn];
int main()
{
memset(a,-1,sizeof(a));
int n,m;
cin >> n >> m;
for(int i=0;i<m;++i)
{
int l,r;
cin >> l >> r;
a[l]=r;
}
int res=0;
for(int i=1;i<=n;++i)
if(a[i]==-1)
++res;
cout << res << endl;
return 0;
}
*/
2)并查集模型:
/**
2)并查集模型:
*/
/**
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=110;
int fath[maxn];
int FindFather(int x); //返回x所属集合的根节点
void Union(int a,int b); //合并两个不同的集合
int main()
{
memset(fath,-1,sizeof(fath));
int n,m;
cin >> n >> m;
for(int i=0;i<m;++i)
{
int 3)路径压缩:将集合的每个子孩子的父亲节点都设置为根节点;
以便为后面的Find函数减低查找时间;对Find进行优化;a,b;
cin >> a >> b;
Union(a,b);
}
int res=0;
for(int i=1;i<=n;++i)
if(fath[i]==-1)
++res;
cout << res << endl;
return 0;
}
int FindFather(int x) //返回x所属集合的根节点
{
while(fath[x]>=0)
x=fath[x];
return x;
}
void Union(int a,int b) //合并两个不同的集合
{
int fa=FindFather(a);
int fb=FindFather(b);
if(fa!=fb)
fath[fa]=fb;
}
*/
3)并查集求每个集合的元素个数;
/**
3)并查集求每个集合的元素个数;
*/
/**
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=110;
int fath[maxn];
int FindFather(int x); //返回x所属集合的根节点
void Union(int a,int b); //合并两个不同的集合
int main()
{
memset(fath,-1,sizeof(fath));
int n,m;
cin >> n >> m;
for(int i=0;i<m;++i)
{
int a,b;
cin >> a >> b;
Union(a,b);
}
// int res=0;
for(int i=1;i<=n;++i)
if(fath[i]<0)
cout << -fath[i] << endl;
return 0;
}
int FindFather(int x) //返回x所属集合的根节点
{
while(fath[x]>=0)
x=fath[x];
return x;
}
void Union(int a,int b) //合并两个不同的集合
{
int fa=FindFather(a);
int fb=FindFather(b);
if(fa!=fb)
{
if(fath[fa]<fath[fb])
{
fath[fa]+=fath[fb];
fath[fb]=fa;
}
else
{
fath[fb]+=fath[fa];
fath[fa]=fb;
}
}
}
*/
4)并查集使用路径压缩求解:
/**
4)并查集使用路径压缩求解:
*/
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=110;
int fath[maxn];
int IsRoot[maxn]={0};
int FindFather(int x); //返回x所属集合的根节点
void Union(int a,int b); //合并两个不同的集合
int main()
{
memset(fath,-1,sizeof(fath));
int n,m;
cin >> n >> m;
for(int i=0;i<m;++i)
{
int a,b;
cin >> a >> b;
Union(a,b);
}
for(int i=1;i<=n;++i)
if(fath[i]<0)
IsRoot[i]=abs(fath[i]);
vector<int> res;
for(int i=1;i<=n;++i)
if(IsRoot[i]>0)
res.push_back(IsRoot[i]);
cout << res.size() << endl;
for(auto a:res)
cout << a << endl;
return 0;
}
int FindFather(int x) //返回x所属集合的根节点
{
if(fath[x]<0)
return x;
else
return fath[x]=FindFather(fath[x]);
}
void Union(int a,int b) //合并两个不同的集合
{
int fa=FindFather(a);
int fb=FindFather(b);
if(fa!=fb)
{
if(fath[fa]<fath[fb])
{
fath[fa]+=fath[fb];
fath[fb]=fa;
}
else
{
fath[fb]+=fath[fa];
fath[fa]=fb;
}
}
}