POJ 1182食物链 种类并查集的经典
Posted randy-lo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1182食物链 种类并查集的经典相关的知识,希望对你有一定的参考价值。
题目链接:http://icpc.njust.edu.cn/Problem/Pku/1182/
题意:给出动物之间的关系,有几种询问方式,问是真话还是假话。
定义三种偏移关系:
x->y 偏移量0时 x和y同类
x->y 偏移量1时 x被y吃
x->y 偏移量2时 x吃y
定义 rela[x]=rx->x;
如x,y不在同一个集合中,
由rx->ry=rx->x + x->y + y->ry=(rx->x)+(x->y)-(ry->y)可得
rx->ry=rela[ry]=rela[x]+rela[y]+(x->y);
由于关系仅限0,1,2,三种,对上面关系加三后取模才是正确的关系;
如果x,y在同一个集合中,
x->y=x->rx+rx->x;
所以x->y=(3-rela[x]+rela[y])%3;
种类并查集的问题我们必须清楚初始状况是什么样的还有状态的转移方程是什么。
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define maxn 50005 5 int n,k; 6 int fa[maxn],rela[maxn];//分别表示父亲、子节点和父节点的关系 7 int ans; 8 void init() 9 { 10 for(int i=1;i<=n;i++) 11 { 12 fa[i]=i; /*relation:0、同类 1、吃2、被吃*/ 13 rela[i]=0;//初始状态下它和本身在一个集合中,关系为同类 14 } 15 ans=0; 16 } 17 int find(int x) 18 { 19 if(x==fa[x])return fa[x]; 20 else 21 { 22 int tmp=fa[x]; 23 fa[x]=find(fa[x]); 24 25 rela[x]=(rela[tmp]+rela[x])%3;//更新x与x的新的根结点的关系,ppx->x=ppx->px+px->x=rela[ppx]+real[px]; 26 return fa[x]; 27 } //向量模式,rela为rootx->x的向量方向;为保证结果在[0,2]区间内,对3取模; 28 } 29 int main() 30 { 31 cin>>n>>k; 32 init(); 33 int f,a,b; 34 for(int i=1;i<=k;i++) 35 { 36 scanf("%d%d%d",&f,&a,&b); 37 if(a>n||b>n) 38 { 39 ans++; 40 continue; 41 } 42 if(f==2&&a==b)//x吃x ,不合法, 43 { 44 ans++; 45 continue; 46 } 47 int px=find(a); 48 int py=find(b); 49 if(px!=py) //如果关系还未建立则建立关系 //合并的操作和查询是否正确的操作在主函数体中一起完成 50 { 51 fa[py]=px; 52 rela[py]=(3+rela[a]+(f-1)-rela[b])%3; 53 } 54 else 55 { 56 if(f==1&&rela[a]!=rela[b])//说是同类然而 计算得并不是,则说了假话 57 { 58 ans++; 59 continue; 60 } 61 if(f==2&&(3+rela[b]-rela[a])%3!=f-1)//两者之间三种状态题目中只有两种描述方式 62 { 63 ans++; 64 continue; 65 } 66 } 67 68 } cout<<ans; 69 }
以上是关于POJ 1182食物链 种类并查集的经典的主要内容,如果未能解决你的问题,请参考以下文章