DSL_1_A:解题报告

互质的集合

原题链接: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;
}

猜你喜欢

转载自blog.csdn.net/the_first_snow/article/details/81158117