互质的集合
原题链接:DSL_1_A
-
题目大意
首先读取整数n,创建由0、1、2 ... n-1这样的数组成的集合,并执行以下两种操作:
1. unite(x, y): 合并包含x和包含y的集合
2. same(x, y): 判断x与y是否属于同一集合
-
输入
n q
com1 x1 y1
com2 x2 y2
...
comq xq yq
-
输出
对于每一个com,0表示unite,1表示same。
对于每一个same,x与y为同一集合输出1,否则输出0,每个结果占一行
-
限制
1 ≤ n ≤ 10 000
1 ≤ q ≤ 100 000
-
样例输入
16 20
1 8 0
1 1 13
0 10 14
0 5 4
0 10 11
1 1 5
0 6 2
1 0 9
1 14 15
0 13 9
0 8 12
0 1 2
0 1 5
0 8 4
1 6 8
0 2 3
0 7 6
1 11 10
0 13 12
0 8 9
-
样例输出
0
0
0
0
0
1
1
-
思路
每个节点指定父节点的id,同时指定子节点集合,每次执行unite,只操作对应节点的父节点,并更新对应关系
-
代码
#include<cstdio>
#include<list>
#define NMAX 10005
#define NUL -1
using namespace std;
short n;
struct Node{
short parent;
list<int> sub;
}nodes[NMAX];
void init(){//初始化父节点
for(short i=0;i<n;i++)
nodes[i].parent =NUL;
}
void unite(short a, short b){//合并
short aParent = (nodes[a].parent==NUL)?a:nodes[a].parent;//a的父节点
short bParent = (nodes[b].parent==NUL)?b:nodes[b].parent;//b的父节点
if(aParent==bParent) return;//已属于同一集合
nodes[bParent].parent = aParent;//b父节点指向a的父节点
nodes[aParent].sub.push_front(bParent);//a父节点的子节点列表添加b父节点
while(!nodes[bParent].sub.empty()){//将b父节点下的所有子节点移动到a父节点的子节点列表
short firstNode = *(nodes[bParent].sub.begin());//a的父节点的子节点列表中的首节点
nodes[aParent].sub.push_front(firstNode);//向b父节点的子节点列表添加该节点
nodes[firstNode].parent = aParent;//更新该节点的父节点
//printf("\n ==== \nsub node's value:%d\n ==== \n");
nodes[bParent].sub.pop_front();//清除已添加的节点
}
/*printf("\n============= now testing =============");//迭代子节点列表内所有元素
for(int i=0;i<n;i++){
printf("\nnode%d: parent: %d\tsub nodes: ", i, nodes[i].parent);
for(list<int>::iterator it = nodes[i].sub.begin(); it!=nodes[i].sub.end();it++){
printf("%d ", *it);
}
}
printf("\n================ test ended ================\n");*/
}
bool same(short a, short b){//检验是否属于同一集合
a = (nodes[a].parent==NUL)?a:nodes[a].parent;//a的父节点
b = (nodes[b].parent==NUL)?b:nodes[b].parent;//b的父节点
return a == b;//a的父节点不为空且a、b的父节点相同
}
int main(){
//freopen("D:/works/C++200/try137_AOJ_DSL_1_A/test.txt", "r", stdin);
int ope,t,a,b;
scanf("%d%d", &n, &t);
init();
while(t--){
scanf("%d%d%d", &ope, &a, &b);
if(ope)
printf("%d\n", same(a, b));
else unite(a, b);
}
return 0;
}