-
E - 食物链
- POJ - 1182
- 中文题意:第一种说法是"1 X Y",表示X和Y是同类。 第二种说法是"2 X Y",表示X吃Y。
- 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。
- 当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
- 1) 当前的话与前面的某些真的话冲突,就是假话;
- 2) 当前的话中X或Y比N大,就是假话;
- 3) 当前的话表示X吃X,就是假话。
- 思路:并查集的处理思路,统一与根节点建立联系方便查询,路径压缩过程有所改变,如果本身是根节点
- 那么无需处理直接返回,如果需要往上查询则记录下当前u的父亲节temp点然后进行递归直到根节点开始更新回溯
- 更新u——>根节点的关系时:
-
num[u].val=(num[u].val+num[temp].val)%3
- 然后先更新不断回溯即可
- 这里的取余是根据题目的情况特殊规律,把关系看做指向根节点的向量,把(0-同类)(1-被根吃)(2-吃根节点)
- 看做之间的关系可以发现 进行关系传递是是满足向量加法的,但是不能超出这三种情况需要对三进行取余
-
#include<iostream> #include<stdio.h> using namespace std; #define maxn 50555 struct node { int fa,val; } num[maxn]; int root (int u) { if(u==num[u].fa) return u; int temp=num[u].fa; num[u].fa=root(temp); num[u].val=(num[u].val+num[temp].val)%3; return num[u].fa; } int n,q,ans,op,u,v,fu,fv; int main() { scanf("%d%d",&n,&q); ans=0; for(int i=1; i<=n; i++) { num[i].fa=i; num[i].val=0; } while(q--) { scanf("%d%d%d",&op,&u,&v); if(u>n||v>n) { ans++; continue; } if(op==2&&u==v) { ans++; continue; } fu=root(u); fv=root(v); if(op==1) { if(fu==fv) { if(num[u].val!=num[v].val) ans++; } else if(fu!=fv) { num[fv].fa=fu; num[fv].val=(3-num[v].val+num[u].val)%3; } } else if(op==2) { if(fu==fv) { if((num[v].val+3-num[u].val)%3!=1) ans++; } else if(fu!=fv) { num[fv].fa=fu; num[fv].val=(3-num[v].val+num[u].val+1)%3; } } } printf("%d\n",ans); return 0; }
E - 食物链 POJ - 1182 -带权并查集
最新推荐文章于 2022-01-18 09:54:45 发布