传送门

 

1.并查集骗分(数据太水,比正解还快。。。)

我们知道,并查集有一步操作叫“路径压缩”,但是本题的并查集我们不能路径压缩,否则就无法进行Destroy操作。那每一步操作我们应该怎么做呢?

对于Connect x y操作,先把x变成集合的根,之后root[x] = y;

对于Destroy x y操作,先把x变成集合的根,此时root[y]必然为x,令root[y] = y即可。

对于Query x y操作,看看x和y所在集合的根是不是一样的就好了。

那么如何把x变成集合的根呢?只要把从x到根路径上的每一条边反向即可,所以不能进行路径压缩。

 

其实并查集的解法也有用 lct 的思想的。

在这里,并查集中的两点之间的边就表示连接两个洞穴之间的边,非常的直接。。

注意一个细节 : 题目中说——无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径

也就是说不会有环!这也正是能用并查集做的原因之一。

 

——代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define N 10001
 4 
 5 int n, m;
 6 int f[N];
 7 
 8 inline int read()
 9 {
10     int x = 0, f = 1;
11     char ch = getchar();
12     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
13     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
14     return x * f;
15 }
16 
17 inline int find(int x)
18 {
19     while(x ^ f[x]) x = f[x];
20     return x;
21 }
22 
23 inline void make_root(int x, int c)
24 {
25     if(x ^ f[x]) make_root(f[x], x);
26     f[x] = c;
27 }
28 
29 int main()
30 {
31     int i, j, x, y, fx, fy;
32     char s[10];
33     n = read();
34     m = read();
35     for(i = 1; i <= n; i++) f[i] = i;
36     for(i = 1; i <= m; i++)
37     {
38         scanf("%s", s);
39         x = read();
40         y = read();
41         if(s[0] == 'Q') find(x) == find(y) ? puts("Yes") : puts("No");
42         else if(s[0] == 'C') make_root(x, x), f[x] = y;
43         else make_root(x, x), f[y] = y;
44     }
45     return 0;
46 }
View Code

相关文章:

  • 2022-02-26
  • 2021-12-16
  • 2022-02-28
  • 2021-10-01
  • 2021-06-14
  • 2021-11-09
  • 2021-09-16
猜你喜欢
  • 2021-06-08
  • 2022-01-29
  • 2021-07-11
  • 2022-01-09
  • 2022-02-20
  • 2021-09-03
  • 2021-07-22
相关资源
相似解决方案