poj1182(带权并查集)

题目链接:http://poj.org/problem?id=1182

题意:题目告诉有  3  种动物,互相吃与被吃,现在告诉你  m  句话,其中有真有假,叫你判断假的个数  (  如果前面没有与当前话冲突的,即认为其为真话  )。每句话开始都有三个数 D A B,当D = 1时,表示A 和B是同类,当D = 2时表示A 吃 B。

思路:

想了好久也没有思路,数据量这么大,感觉只能用并查集来完成,之后参考了巨巨的博客:https://www.cnblogs.com/liuxin13/p/4668205.html。

不禁赞叹,真的是好题啊。好了,这道题是一个带权并查集的题。对于每一句话,首先可能出现直接能判定为假的情况,即输入的数有大于n的或者D=2且A=B时。之后就需要并查集了。不访设A->B的关系中0表示同类、1表示A吃B、2表示A被B吃。则输入的D减一后即代表A->B表示的关系,现在就将需要把有关系的点并在一起,用root[i]表示点i的祖先,f[i]表示点i与其祖先的关系,可能为0,1,2。

接下来先推一个公式:

这样题目就可以继续进行了。输入d a b,用ra,rb表示a,b的祖先。若能直接判断为假话,则++res,继续下一句话,否则:

1.ra!=rb:那么将a,b合并。路径:root[rb]=ra。关系:f[rb]=rb->ra=(rb->a+a->ra)%3=((6-a->b-b->rb)%3+a->ra)%3=(6-a->b-b->rb+a->ra)%3=(6-(d-1)+f[a]-f[b])%3。

2.ra==rb:查询a->b是否等于(d-1)。判断f[a]==((d-1)+f[b])%3是否成立,若不成立则为错话。

在getr函数中要路径压缩和权值压缩(看代码,由上面推的公式就明白了)。

详见代码:

 1 #include<cstdio>
 2 using namespace std;
 3
 4 int n,k,res,d,a,b;
 5 int root[50005],f[50005];
 6
 7 int getr(int kk){
 8     if(root[kk]==kk) return kk;
 9     else{
10         int tmp=root[kk];
11         root[kk]=getr(root[kk]);
12         f[kk]=(f[kk]+f[tmp])%3;
13         return root[kk];
14     }
15 }
16
17 int main(){
18     scanf("%d%d",&n,&k);
19     for(int i=1;i<=n;++i)
20         root[i]=i,f[i]=0;
21     while(k--){
22         scanf("%d%d%d",&d,&a,&b);
23         int ra=getr(a),rb=getr(b);
24         if(a>n||b>n||(d==2&&a==b))
25             ++res;
26         else if(ra==rb){
27             if(f[a]!=(d-1+f[b])%3)
28                 ++res;
29         }
30         else{
31             root[rb]=ra;
32             f[rb]=(6-(d-1)+f[a]-f[b])%3;
33         }
34     }
35     printf("%d\n",res);
36     return 0;
37 }

原文地址:https://www.cnblogs.com/FrankChen831X/p/10459023.html

时间: 2024-10-11 15:53:09

poj1182(带权并查集)的相关文章

poj1182 食物链(带权并查集)

题目链接 http://poj.org/problem?id=1182 思路 前面做的带权并查集的权值记录该结点与其父结点是否是同一类,只有两种取值情况(0,1),在这题中某结点a和其父结点b的取值共有三种情况:a和b同类:a被b吃:a吃b,对应三种情况,r[a]的取值分别为0,1,2.这题的难点是递推公式,路径压缩递推公式为r[x] = (r[x] + r[t]) % 3,合并集合递推公式为r[ra] = (3 - r[a] + d - 1 + r[b]) % 3,递推公式形式的推导可以参考这

【POJ1182】 食物链 (带权并查集)

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之

带权并查集 poj1182

首先要注意核心代码 int find(int i){    if(i == fa[i])        return fa[i];    int tt = find(fa[i]);    num[i] = (num[i] + num[fa[i]]) % 3;    fa[i] = tt;    return fa[i];}不能写成 int find(int i){    if(i == fa[i])        return fa[i];    fa[i] = find(fa[i]);   

poj1182食物链,经典带权并查集

动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之一时,这句话就是假话,否

并查集例题02.带权并查集(poj1182)

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A.现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种.有人用两种说法对这N个动物所构成的食物链关系进行描述:第一种说法是"1 X Y",表示X和Y是同类.第二种说法是"2 X Y",表示X吃Y.此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之一时,这句

并查集练习2(带权并查集)

明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~ poj1703 Find them, Catch them (带权并查集) 1 #include<cstdio> 2 const int N=1e5+1; 3 int f[N]; 4 int r[N];//表示与父节点的关系,0同类,1不同类 5 int n; 6 void init(){ 7 for(int i=1;i<=n;++i){ 8 f[i]=i; r[i]=0; 9 } 10 } 11 int fin(int x){ 12 i

poj2492 A Bug&#39;s Life【带权并查集】

题目链接:http://poj.org/problem?id=2492 题目描述:找基佬游戏(汗-_-b)有个hentai科学家研究虫子种群,不断地给出二元组xy,表示x和y是异性交往,但是可能会出现矛盾(找到基佬),比如1与2是异性恋,2与3是异性恋,却又告诉你1和3是异性恋.问种群中存不存在基佬败类 思路:与poj1182“食物链”几乎一样,还简单一点,毕竟只有两类物品.par[i]表示父节点,d[i]表示偏移量,0为同性,1为异性.不过要注意的一点是所有合并的过程要对二取模,比如x找到根结

hdu3038(带权并查集)

题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示从第x,个元素到第y个元素的和为d(包括x, 和y), 问m行输入里面有几个是错误的(第一个输入是正确的); 思路: 很显然带权并查集咯,我们可以用距离的概念代替和的概念比较好理解一点,d表示x到y的和即x到y的距离; 可以用rank[x]表示x到其父亲节点的距离,  将正确的距离关系合并到并查集中

【poj 1988】Cube Stacking(图论--带权并查集 模版题)

题意:有N个方块,M个操作{“C x”:查询方块x上的方块数:“M x y”:移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法:带权并查集.每堆方块作为一个集合,维护3个数组:fa[x]表示x方块所在堆的最顶部的方块:d[x]表示x方块所在堆的最底部的方块:f[x]表示x方块方块x上的方块数. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<