poj食物链,经典带权并查集
来源:互联网 发布:软件开发里程碑计划 编辑:程序博客网 时间:2024/04/29 11:15
题目描述
动物王国中有三类动物 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 句话有的是真
的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
• 当前的话与前面的某些真的话冲突,就是假话
• 当前的话中 X 或 Y 比 N 大,就是假话
• 当前的话表示 X 吃 X,就是假话
你的任务是根据给定的 N 和 K 句话,输出假话的总数。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <string>#include <cmath>#include <cstdlib>#include <vector>#include <queue>#include <set>#include <map>using namespace std;typedef long long ll; const int maxn=1e5+10;int fa[maxn],rnk[maxn];//rnk点与根的关系int n,k;void init(int x){ for(int a=0;a<=x;a++){ fa[a]=a; rnk[a]=0; }}int findfa(int x){ if(fa[x]==x) return x; else{ int mid=fa[x]; fa[x]=findfa(fa[x]);//压缩 rnk[x]=(rnk[x]+rnk[mid])%3;//节点与根的关系 rnk[mid]是mid与根结点的关系 return fa[x];//第二个rnk[x]是当前的点到压缩前的根的关系,rnk【mid】是之前的根到当前的根的关系,两者相加即为当前的点到当前的根的关系 }}void merge(int r,int x,int y){ int fx=findfa(x); int fy=findfa(y); if(fx!=fy){ fa[fx]=fy; rnk[fx]=(rnk[y]-rnk[x]+r+3)%3; }}bool check(int a,int b,int c){ if (b>n||c>n||b<1||c<1) { return false; } if(a==1&&b==c) return false; int fb=findfa(b); int fc=findfa(c); if(fb==fc) return a==(rnk[b]-rnk[c]%3+3)%3; else return true;}int main(){ int ans = 0; scanf("%d %d",&n,&k); init(n); for (int a=0; a<k; a++) { int o,p,q; cin>>o>>p>>q; o--; if(check(o,p,q)) merge(o,p,q); else ans++; } printf("%d\n",ans); return 0;}
阅读全文