zoukankan      html  css  js  c++  java
  • [luoguP2147] [SDOI2008]Cave 洞穴勘测(并查集 || lct)

    传送门

    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

    2.lct(正解)

    就是模板啦

    ——代码

      1 #include <cstdio>
      2 #include <iostream>
      3 #define N 10001
      4 #define swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
      5 
      6 int n, m;
      7 int f[N], rev[N], son[N][2], s[N], size[N];
      8 
      9 inline int read()
     10 {
     11     int x = 0, f = 1;
     12     char ch = getchar();
     13     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
     14     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
     15     return x * f;
     16 }
     17 
     18 inline bool isroot(int x)
     19 {
     20     return son[f[x]][0] ^ x && son[f[x]][1] ^ x;
     21 }
     22 
     23 inline int get(int x)
     24 {
     25     return son[f[x]][1] == x;
     26 }
     27 
     28 inline void pushdown(int x)
     29 {
     30     if(x && rev[x])
     31     {
     32         swap(son[x][0], son[x][1]);
     33         if(son[x][0]) rev[son[x][0]] ^= 1;
     34         if(son[x][1]) rev[son[x][1]] ^= 1;
     35         rev[x] = 0;
     36     }
     37 }
     38 
     39 inline void rotate(int x)
     40 {
     41     int old = f[x], oldf = f[old], wh = get(x);
     42     
     43     if(!isroot(old))
     44         son[oldf][son[oldf][1] == old] = x;
     45     f[x] = oldf;
     46     
     47     son[old][wh] = son[x][wh ^ 1];
     48     f[son[old][wh]] = old;
     49     
     50     son[x][wh ^ 1] = old;
     51     f[old] = x;
     52 }
     53 
     54 inline void splay(int x)
     55 {
     56     int i, fa, t = 0;
     57     s[++t] = x;
     58     for(i = x; !isroot(i); i = f[i]) s[++t] = f[i];
     59     for(i = t; i >= 1; i--) pushdown(s[i]);
     60     for(; !isroot(x); rotate(x))
     61         if(!isroot(fa = f[x]))
     62             rotate(get(x) == get(fa) ? fa : x);
     63 }
     64 
     65 inline void access(int x)
     66 {
     67     for(int t = 0; x; t = x, x = f[x]) splay(x), son[x][1] = t;
     68 }
     69 
     70 inline void reverse(int x)
     71 {
     72     access(x);
     73     splay(x);
     74     rev[x] ^= 1;
     75 }
     76 
     77 inline int find(int x)
     78 {
     79     access(x);
     80     splay(x);
     81     while(son[x][0]) x = son[x][0];
     82     return x;
     83 }
     84 
     85 inline void link(int x, int y)
     86 {
     87     reverse(x);
     88     f[x] = y;
     89     splay(x);
     90 }
     91 
     92 inline void cut(int x, int y)
     93 {
     94     reverse(x);
     95     access(y);
     96     splay(y);
     97     son[y][0] = f[x] = 0;
     98 }
     99 
    100 int main()
    101 {
    102     int i, j, x, y;
    103     char s[10];
    104     n = read();
    105     m = read();
    106     for(i = 1; i <= m; i++)
    107     {
    108         scanf("%s", s);
    109         x = read();
    110         y = read();
    111         if(s[0] == 'Q') find(x) == find(y) ? puts("Yes") : puts("No");
    112         if(s[0] == 'C') link(x, y);
    113         if(s[0] == 'D') cut(x, y);
    114     }
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    批处理
    命名规则
    注释
    HTML DOM属性
    OLTP
    修改HTML元素
    HTML
    工具资源系列之给虚拟机装个centos
    工具资源系列之给虚拟机装个windows
    工具资源系列之给mac装个虚拟机
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7018198.html
Copyright © 2011-2022 走看看