题意 : 中文题就不说题意了……

分析 : 通过普通并查集的整理归类, 能够单纯地知道某些元素是否在同一个集合内。但是题目不仅只有种类之分, 还有种类之间的关系, 即同类以及吃与被吃, 而且重点是题目问的并不是种类是否在一个集合内, 而是考察给出的关系是否矛盾。在解释之前, 先明白一个问题, 对于给出的关系, 如果我不能通过前面的信息来推断出来, 是不是不能够判断现在给出关系的对错?那就将这个信息作为真命题并存储起来, 方便后面判断。有了刚刚前面的陈述, 可以知道两个东西=>

对于这个题目并查集存储的是关系(即同类或吃与被吃) && 只有能够相互之间确立关系的才能合并同一个集合内 

那如何使用并查集存储关系呢?题目给出的是两个物种和它们间的关系, 我们可以将给出 的两个物种看成两个并查集的节点, 然后将连接两个节点的边带上相应的权值代表这两个节点之间的关系, 为了通俗和具体一点, 就举例说明, 例如题目给出 1 1 2 (即1和2是同类), 存储步骤以及图示如下

①用一个father数组来存储并查集内的父子关系, 这里用father[1] = 2将1设置为2的父节点。(常规并查集操作)

②用relation数组存储连接这两个点的权值(即关系)relation[1]=x, 这里的x需要进行定义, 这里定义如下 0=>同类、1=>父节点吃子节点、2=>子节点吃夫节点(这样的定义并非随意, 后面绿色文字有说明), 所以刚刚的式子就应该是relation[1]=0。

③知道了单独两个物种的关系, 那这两个物种就属于一个集合了。但是1和2有可能并非是单独的物种, 换句话说就是1和2在合并之前可能就已经属于某一个集合了, 刚刚前面也说到, 一旦在一个集合里面, 那这个集合里面的所有元素都能互相确立关系, 那1和2能够确定关系, 那原来1所在的集合肯定也能和2原来所在的集合之间所有的元素确立关系, 所以这两个集合需要合并!

④也就像刚刚③所说, 1和2有可能并非只是单独个体, 有可能已经和其他元素构成集合, 在合并的过程中, 还需要进行路径压缩才能发挥并查集的高效!

如果做完刚刚说的步骤, 那在每一次给出的关系就能通过并查集的查找来知道这句话是否有错!但是很明显, 因为有了权值的设置, 要进行③的集合合并和④的路径压缩就要同时考虑将relation数组进行相应的变化, 因为relation[k]记录的只是k与父节点的关系, 如果进行了路径压缩, 那relation[k]就要变成k与k所在集合根节点的关系了。接下来就是用到向量的地方了!以下来说说如何使用向量知识, 进行集合合并和路径压缩

集合合并:

如果输入=>R fir sec(fir物种和sec物种有R这种关系), 那我们可以得到的已知条件是 fir 和 sec 所在集合的根节点(假设已经经过路径压缩) Fir_root 和 Sec_root, 假设我们将Sec_root接到Fir_root上, 那就能得到如下图, 则我们所要求的就是红色箭头所指代的relation, 然后将节点进行常规的并查集合并, 就能完成集合合并操作了, 也就是relation[Sec_root] = (relation[fir]+(R-1)-relation[sec]+3)%3, father[sec_root] = fir_root, 这里再说明一下relation计算的式子, %3的原因是要保证值在0~2之间, 由于有-relation[sec]操作, 所以为了避免relation[sec]过大, 使得整条模三的式子为负数, 所以进行+3操作!这里需要注意的是, R只是题目的输入(即1或2), 而我们刚刚定义的relation的取值x只有三种情况, 两者的关系是什么呢?也就是如何用输入的R得到实际我们定义的x?如果输入R=1, 对应的x=0, 而R=2, 对应的x=1, 所以x = R-1就是当前物种fir和sec的关系, 这也就是刚刚说为什么x的那三个值并非随意定义的原因。

路径压缩:

操作呢, 就如下图所示, 可见除了根节点自己所有的节点最后的父亲都是根节点, 同样的, relation的更新也可以采用向量的知识, 代码就是可以先通过递归找到根结点, 然后代码中递归的过程就是下图①~④的过程, 是从根到末尾节点的更新, 具体看代码思考

至此就完成了所有操作, 只要在操作之前判断语句是否和之前给出的关系有矛盾, 具体的还是可以用向量来思考。

留下了递归进行路径压缩中如何变relation 和 判断是否是错误语句这两个问题, 看代码即可, 相信这个是不难思考的!

  1. #include<stdio.h>
  2. #include<iostream>
  3. using namespace std;
  4. ;
  5. int father[maxn], relation[maxn], n, k, nCase;
  6. int findset(int x)//递归寻找根节点
  7. {
  8. if(x == father[x]) return x;
  9. int temp = father[x];//temp == x的父节点
  10. father[x] = findset(temp);//继续寻找根节点
  11. relation[x] = ( relation[temp] + relation[x] )%;//通过向量相加可以得出现在x与根节点的关系
  12. return father[x];
  13. }
  14. int main(void)£¬
  15. {
  16. scanf("%d %d", &n, &k);
  17. ; i<=n; i++){
  18. father[i] = i;
  19. relation[i] = ;
  20. }
  21. ;
  22. while(k--){
  23. scanf("%d %d %d", &command, &fir, &sec);
  24. || sec<= || fir>n || sec>n) ans++;
  25. && fir==sec) ans++;
  26. else{
  27. int Fir_root = findset(fir);
  28. int Sec_root = findset(sec);
  29. if(Fir_root != Sec_root){//如果两个物种并不在一个关系, 也就是无法知道关系, 则合并
  30. father[Sec_root] = Fir_root;
  31. relation[Sec_root] = ( + (command - ) + relation[fir] - relation[sec] )%;
  32. }else{
  33. ) {if(relation[fir] != relation[sec]) ans++;}//如果1就代表同类, 则fir和sec与根的关系应该是一样的
  34. - relation[fir] + relation[sec])% != command- ) ans++;}//如果2就代表fir吃sec即command-1, 左边式子同样根据向量运算得到
  35. }
  36. }
  37. }
  38. printf("%d\n", ans);
  39. ;
  40. }

POJ 1182 食物链 (带权并查集 && 向量偏移)的更多相关文章

  1. poj 1182 食物链 带权并查集

    食物链是并查集的进阶运用的一道非常经典的题目. 题目如下: 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A, ...

  2. POJ 2492 A Bug's Life (带权并查集 && 向量偏移)

    题意 : 给你 n 只虫且性别只有公母, 接下来给出 m 个关系, 这 m 个关系中都是代表这两只虫能够交配, 就是默认异性, 问你在给出的关系中有没有与异性交配这一事实相反的, 即同性之间给出了交配 ...

  3. K - Find them, Catch them POJ - 1703 (带权并查集)

    题目链接: K - Find them, Catch them POJ - 1703 题目大意:警方决定捣毁两大犯罪团伙:龙帮和蛇帮,显然一个帮派至少有一人.该城有N个罪犯,编号从1至N(N<= ...

  4. POJ - 2912 Rochambeau (带权并查集+枚举)

    题意:有N个人被分为了三组,其中有一个人是开了挂的.同组的人的关系是‘=’,不同组的人关系是‘<’或'>',但是开了挂的人可以给出自己和他人任意的关系.现在要根据M条关系找出这个开了挂的人 ...

  5. A Bug's Life POJ - 2492 (带权并查集)

    A Bug's Life POJ - 2492 Background Professor Hopper is researching the sexual behavior of a rare spe ...

  6. poj1182 食物链 带权并查集

    题目传送门 题目大意:大家都懂. 思路: 今天给实验室的学弟学妹们讲的带权并查集,本来不想细讲的,但是被学弟学妹们的态度感动了,所以写了一下这个博客,思想在今天白天已经讲过了,所以直接上代码. 首先, ...

  7. POJ 1182 食物链(经典带权并查集 向量思维模式 很重要)

    传送门: http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: ...

  8. poj 1182:食物链(种类并查集,食物链问题)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 44168   Accepted: 12878 Description ...

  9. POJ 1182 食物链(种类并查集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 63592   Accepted: 18670 Description ...

随机推荐

  1. 简述Js中,判断对象为空对象的几种方式

    1.空对象.空引用以及undefined三种概念的区别 空对象:是对象,但它的值是指向没有任何属性的对象的引用, {}是指 不含任何属性 的对象,当然对象属性包括 字面值和函数: 空引用:obj=nu ...

  2. 2019JAVA第四次实验报告

    JAVA实验报告 班级 计科二班 学号 20188442 姓名 吴怡君 完成时间 2019/9/29 评分等级 实验四 类的继承 1.实验目的 掌握类的继承方法: 变量的继承和覆盖,方法的继承.重载和 ...

  3. CDH的ntp时间同步

    云服务器: ntpq -p ntpdate -u 10.52.255.1  #手动同步 自建NTP服务器: https://www.cnblogs.com/yinzhengjie/p/9480665. ...

  4. [codeforces1234F]Yet Another Substring Reverse

    题目链接 大致题意为将某个子串进行翻转后,使得不包含相同字符的字符子串长度最长.只能翻转一次或零次. 设一个子串的状态为包含字符的二进制.如子串为$abacd$,则状态为$00000000000000 ...

  5. priority_queue的常见用法

    priority_queue的常见用法 priority_queue是什么? 优先队列 底层实现用堆来实现 每次队首的优先级最大 priority_queue的定义 引入头文件 # include & ...

  6. 洛谷 P1472 奶牛家谱 Cow Pedigrees 题解

    题面 这道题我觉得是个不错的题: 根据题意可以较清晰的发现ans只和n和k有关:(因为输入的只有这两个数啊~): 那么设f[i][j]表示前i层用了j个节点的方案数,g[i][j]表示深度小于等于i并 ...

  7. Android 之 悬浮窗口

    1. 创建并设置  WindowManager  类 WindowManager mWindowManager; // 取得系统窗体 mWindowManager = (WindowManager) ...

  8. k路归并

    public static int[] k_merge(ArrayList<int[]> k_array) { if(CollectionUtils.isEmpty(k_array)){ ...

  9. mysql优化--explain关键字

    MySQL性能优化---EXPLAIN 参见:https://blog.csdn.net/jiadajing267/article/details/81269067 参见:https://www.cn ...

  10. linux复习4:文件和目录

    7一.linux文件 1.linux文件的扩展名:文件扩展名是文件名最后一个点之后的部分,下面列出了其中一部分 (1)压缩文件和归档文件 压缩和归档的文件扩展名及其含义如下. .bz2:使用bzip2 ...