数据结构MOOC
PTA习题
这道题考察并查集的操作,合并以及找根结点
机翻:
1、条件准备
node是数组存放1-N结点的根节点的,n为总结点数
#include <iostream>
using namespace std;
const int N = 1e4 + 5;
int node[N];
int n;
先初始化,每一个结点的根节点是本身。
然后循环输入每一组数据,遇到S就退出。
遇到I就将两个结点插入到一棵树中,用insert函数实现
遇到C就检查两个结点是否在同一棵树中,用check实现o
最后跳出循环,看看一共有几棵树,并输出对应语句,用component函数实现
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
node[i] = i;
while (1)
{
char c;
cin >> c;
if (c == 'S')
break;
int a, b;
cin >> a >> b;
if (c == 'I')
insert(a, b);
else if (c == 'C')
check(a, b);
}
component();
return 0;
}
2、find函数
该函数是找结点所在树的根节点。如果下标与值相等,则它自己就是根节点。
否则沿着路径找其对应根节点,并更新该结点的祖宗结点为返回的根节点
这个操作保证每次find查找完,所遍历的结点它们的每个结点的祖宗结点都更新了
int find(int a)
{
if (node[a] == a)
return a;
else
return node[a] = find(node[a]);//路径压缩
}
3、insert函数
将两个结点所在树合并,先找到它们对应的祖宗结点。
这里采用值大的作为新的根节点,并把另一个祖宗结点的值改为新的根节点。
void insert(int a, int b)
{
int parenta = find(a), parentb = find(b);
if (parenta > parentb)
node[parentb] = parenta;
else
node[parenta] = parentb;
}
4、check函数
看看两个结点祖宗结点是否一样,输出对应数据
void check(int a, int b)
{
if (find(a) == find(b))
cout << "yes" << endl;
else
cout << "no" << endl;
}
5、component函数
找一共有多少棵树,只需遍历一遍每个结点,若值为其下标,则它就为这棵树的根节点。
如果只有一棵树,那么所有结点都连起来了,否则输出有多少棵树
void component()
{
int num = 0;
for (int i = 1; i <= n; i++)
if (i == node[i])
num++;
if (num == 1)
cout << "The network is connected.";
else
cout << "There are " << num << " components.";
}
6、总结
这道题运用了并查集的知识,难度不算大,没有用到结构体、指针,较好理解。
完整代码如下:
#include <iostream>
using namespace std;
const int N = 1e4 + 5;
int node[N];
int n;
int find(int a)
{
if (node[a] == a)
return a;
else
return node[a] = find(node[a]);
}
void insert(int a, int b)
{
int parenta = find(a), parentb = find(b);
if (parenta > parentb)
node[parentb] = parenta;
else
node[parenta] = parentb;
}
void check(int a, int b)
{
if (find(a) == find(b))
cout << "yes" << endl;
else
cout << "no" << endl;
}
void component()
{
int num = 0;
for (int i = 1; i <= n; i++)
if (i == node[i])
num++;
if (num == 1)
cout << "The network is connected.";
else
cout << "There are " << num << " components.";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
node[i] = i;
while (1)
{
char c;
cin >> c;
if (c == 'S')
break;
int a, b;
cin >> a >> b;
if (c == 'I')
insert(a, b);
else if (c == 'C')
check(a, b);
}
component();
return 0;
}
附录:并查集相关操作
#define MAXN 1000
typedef int ElementType;
typedef int SetName;
typedef ElementType SetType[MAXN];
void Union(SetType S,SetName root1,SetName root2)
{
if(S[root2]<S[root1])
{
S[root2]+=S[root1];
S[root1]=root2;
}
else
{
S[root1]+=S[root2];
S[root1]=root2;
}
}
SetName find(SetType S,ElementType x)
{
if(S[x]<0)
return x;
else return S[x]=find(S,S[x]);
}