并查集,顾名思义有两个操作:合并和查询。
并就是把两个集合合并到一起。
查就是查询两个节点是否属于同一个集合。
每个节点有一个父节点。一个集合内存在一个唯一的根,判断根的条件就是节点的父节点是不是该节点本身。
合并操作就是把一个集合的根接到另一个集合的根上。
而查询操作就是找两个对象是否有同一个根。
查询过程中可以顺便进行路径压缩以优化后续查询:即让查找路径上所有节点的父节点直接等于根节点。
#include <iostream> #include <algorithm> #include <cstring> #define MAX 200005 using namespace std; int root[MAX]; char names[MAX][50]; unsigned int BKDRHash(char *str) { unsigned int seed = 131; unsigned int hash = 0; while (*str) { hash = hash * seed + (*str++); } return (hash & 0x7FFFFFFF) % MAX; } int get_index(char *str) { int res = BKDRHash(str); while (strlen(names[res]) != 0 && strcmp(str, names[res])) { res++; res %= MAX; } if (strlen(names[res]) == 0) { strcpy(names[res], str); } return res; } int get_root(int a) { if (root[a] == -1) root[a] = a; if (a != root[a]) { root[a] = get_root(root[a]); } return root[a]; } int main() { int n; int op; char s1[50], s2[50]; int a, b; memset(root, -1, sizeof(root)); cin >> n; while (n--) { cin >> op >> s1 >> s2; a = get_index(s1); b = get_index(s2); if (op == 0) { int fa = get_root(a), fb = get_root(b); root[fa] = fb; } else { int fa = get_root(a), fb = get_root(b); if (fa == fb) { cout << "yes" << endl; } else { cout << "no" << endl; } } } return 0; }
时间: 2024-12-14 12:46:47