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

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

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

那如何使用并查集存储关系呢?题目给出的是两个物种和它们间的关系, 我们可以将给出 的两个物种看成两个并查集的节点, 然后将连接两个节点的边带上相应的权值代表这两个节点之间的关系, 为了通俗和具体一点, 就举例说明, 例如题目给出 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 和 判断是否是错误语句这两个问题, 看代码即可, 相信这个是不难思考的!

#include<stdio.h>
#include<iostream>
using namespace std;
;
int father[maxn], relation[maxn], n, k, nCase;
int findset(int x)//递归寻找根节点
{
    if(x == father[x]) return x;
    int temp = father[x];//temp == x的父节点
    father[x] = findset(temp);//继续寻找根节点
    relation[x] = ( relation[temp] + relation[x] )%;//通过向量相加可以得出现在x与根节点的关系
    return father[x];
}
int main(void)£¬
{
    scanf("%d %d", &n, &k);
    ; i<=n; i++){
        father[i] = i;
        relation[i] = ;
    }
    ;
    while(k--){
        scanf("%d %d %d", &command, &fir, &sec);
         || sec<= || fir>n || sec>n) ans++;
         && fir==sec) ans++;
        else{
            int Fir_root = findset(fir);
            int Sec_root = findset(sec);
            if(Fir_root != Sec_root){//如果两个物种并不在一个关系, 也就是无法知道关系, 则合并
                father[Sec_root] = Fir_root;
                relation[Sec_root] = (  + (command - ) + relation[fir] - relation[sec] )%;
            }else{
                ) {if(relation[fir] != relation[sec]) ans++;}//如果1就代表同类, 则fir和sec与根的关系应该是一样的
                 - relation[fir] + relation[sec])% != command- ) ans++;}//如果2就代表fir吃sec即command-1, 左边式子同样根据向量运算得到
            }
        }
    }
    printf("%d\n", ans);
    ;
}

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. 向tabcontrol中添加form

    昨天花了一天的时间去找一个错误,关系是这样的,我添加一个tabcontrol就叫tc1好了,然后在tc1中再动态添加一个父窗体l叫form1,要把form1添加进tabcontrol就要先新建一个ta ...

  2. 第五周总结&实验·

                                                                  本周总结 1.final声明的变量即成为常量,常量不可以修改. 2.子类能够 ...

  3. Java第六周实验+总结

    一.实验目的 (1)掌握类的继承 1.子类继承父类中非private的成员变量和成员方法,同时,注意构造方法不能被子类继承. 2.定义类时若缺省extends关键字,则所定义的类为java.lang. ...

  4. [总集] LOJ 分块1 – 9

    目录 分块9题 出题人hzw的解析 数列分块入门 1 修改:区间加 查询:单点值查询 代码 数列分块入门 2 修改:区间加 查询:区间排名 代码 数列分块入门 6 修改:单点插入 查询:单点值 代码 ...

  5. 面试题 | 数据库笔试题集合·之·SQL语句(2)

    第2章 SQL 语句 2.1 选择2.1.1 DELETE FROM S WHERE 年龄>60 语句的功能是( A ) A.从 S 表中彻底删除年龄大于 60 岁的记录B.S 表中年龄大于 6 ...

  6. 【6.28校内test】T1 Jelly的难题1

    Jelly的难题[题目链接] 废话一句:今天中考出成绩,感觉大家考的都超级棒,不管怎样,愿大家成为最好的自己. 好了废话完了,下面是题解部分: SOLUTION: 首先你可能发生的,是看不懂题: 定睛 ...

  7. hdu3829 二分匹配 最大独立集

    Cat VS Dog Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 125536/65536 K (Java/Others) Problem ...

  8. E - 秋实大哥与战争

    秋实大哥与战争 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit S ...

  9. Python程序结构(sys、os)

    一.Python组成结构 Python程序一般由包package.模块moudle.函数function组成.具体关系如下图:

  10. 32、出任爬虫公司CEO(爬取职友网招聘信息)

    职友集,搜索到全国上百家招聘网站的最新职位.   https://www.jobui.com/rank/company/   打开网址后,你会发现:这是职友集网站的地区企业排行榜,里面含有     本 ...