并查集专题训练地址,注册登录了才能看到题目

并查集是一个树形的数据结构,  可以用来处理集合的问题, 也可以用来维护动态连通性,或者元素之间关系的传递(关系必须具有传递性才能有并查集来维护,因为并查集有压缩路径)。

用并查集来维护元素之间关系的传递, 那么元素与元素之间就有一个权值(带权并查集),那么当路径压缩时,我们需要根据关系的传递性来维护

当父元素变动时,关系的变动。

 

poj1182食物链

给定一些元素之间的关系, 问我们有多少是错误的。 当碰到一个错误时,并不会用它来更新并查集(错误的怎么用来更新?),只会把ans++

我们用0表示与父亲是同类,  用1表示吃父亲 , 用2表示被父亲吃。(这表示的是我与父亲的关系,即箭头是由我指向父亲), 那怎么得到父亲与我的关系呢?

只要将箭头的方向改变, 就得到了父亲与我的关系,  (3-rank[x]) % 3  就是了

 只要明白了箭头方向的改变,关系也可以用公式推导出来

那么下边就好办了, 如果判断是否发生错误呢?

并查集专辑 (poj1182食物链,hdu3038, poj1733, poj1984, zoj3261)

如图,红色的线表示题目给我们的关系, 现在他们在一个集合里面,可以通过运算获得蓝线1,然后再通过计算获得蓝线2, 只要将蓝线2和红线对比,就知道

题目所给的关系是否正确。

 

同理,集合的合并也是一样的

并查集专辑 (poj1182食物链,hdu3038, poj1733, poj1984, zoj3261)

通过红线1,依次算出蓝线1,2,3.    那么就可以进行集合的合并了。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <queue>
  7 #include <stack>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <string>
 12 #include <math.h>
 13 using namespace std;
 14 #pragma warning(disable:4996)
 15 #pragma comment(linker, "/STACK:1024000000,1024000000")
 16 typedef long long LL;                   
 17 const int INF = 1<<30;
 18 /*
 19 路径压缩的时候要保留结点与结点之间的关系, 所以要维护的一个信息是,结点之间的关系
 20 0同类 ,  1被父亲吃,  2吃父亲
 21 */
 22 const int N = 50000 + 10;
 23 int fa[N];
 24 int id[N];//id[u] 表示与父亲之间的边的权值,, 权值为0,1,2三种
 25 int find(int x)
 26 {
 27     if (x == fa[x])
 28         return x;
 29     //路径压缩的时候,由于父亲的改变, 需要改变权值
 30     int tmp = fa[x];
 31     fa[x] = find(fa[x]);
 32     id[x] = (id[x] + id[tmp]) % 3;
 33     return fa[x];
 34 }
 35 int main()
 36 {
 37     int n, m, ans;
 38     int d, a, b;
 39     int fx, fy;
 40     //while (scanf("%d%d", &n, &m) != EOF)
 41     {
 42         scanf("%d%d", &n, &m);
 43         ans = 0;
 44         for (int i = 1; i <= n; ++i)
 45         {
 46             fa[i] = i;
 47             id[i] = 0;
 48         }
 49         while (m--)
 50         {
 51             scanf("%d%d%d", &d, &a, &b);
 52             if (d == 1)
 53             {
 54                 if (a > n || b > n)
 55                     ans++;
 56                 else
 57                 {
 58                     fx = find(a);
 59                     fy = find(b);
 60                     if (fx != fy)
 61                     {
 62                         fa[fy] = fx;
 63                         id[fy] = ((3 - id[b])%3 + (d - 1) + id[a]) % 3;
 64                     }
 65                     else
 66                     {
 67                         if ((3-id[a]+id[b])%3 != 0)
 68                             ans++;
 69 
 70                     }
 71                 }
 72             }
 73             else
 74             {
 75                 if (a > n || b > n)
 76                     ans++;
 77                 else
 78                 if (a == b)
 79                     ans++;
 80                 else
 81                 {
 82                     fx = find(a);
 83                     fy = find(b);
 84                     if (fx != fy)
 85                     {
 86                         fa[fy] = fx;
 87                         id[fy] = ((3 - id[b])%3  + (d - 1) + id[a]) % 3;
 88                     }
 89                     else
 90                     {
 91                         if ((3 - id[a] + id[b])%3 != 1)
 92                             ans++;
 93                     }
 94                 }
 95             }
 96         }
 97         printf("%d\n", ans);
 98     }
 99     return 0;
100 }
View Code

相关文章: