题目描述
动物王国中有三类动物 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 句话,输出假话的总数。
输入输出格式
输入格式:
从 eat.in 中输入数据
第一行两个整数,N,K,表示有 N 个动物,K 句话。
第二行开始每行一句话(按照题目要求,见样例)
输出格式:
输出到 eat.out 中
一行,一个整数,表示假话的总数。
输入输出样例
很明显是并查集 但是又很难下手 不知道该和同类并还是和敌对关系并。。。
有一个非常巧妙地方法 将并查集扩为3*n 1-n表示本体 n+1-2*n表示猎物 2*n+1-3*n表示天敌 所有有关系的全部并一下!
一开始的代码 一直wa
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f #define N 100000+5 int f[3*N]; int find1(int x) { return x==f[x]?x:f[x]=find1(f[x]); } void union1(int a,int b) { int x=find1(a); int y=find1(b); if(x!=y) f[x]=y; } int main() { int n,m; RII(n,m); rep(i,1,3*n)f[i]=i; int cnt=0; rep(i,1,m) { int a,b,c; RIII(a,b,c); if( b>n||c>n||(a==2&&b==c)) { cnt++;continue; } if(a==1) { if(find1(2*c)!=find1(b)&&find1(3*c)!=find1(b)) { union1(c,b); } else cnt++; } else if(a==2) { if(find1(b)==find1(c)) { cnt++;continue; } if(find1(3*b)==find1(c)||find1(2*c)==find1(b)) { cnt++;continue; } union1(2*b,c); union1(3*c,b); union1(2*c,3*b); //union1() } } printf("%d ",cnt); return 0; }
+kn 写成*k 我不wa谁wa。。
还有一个细节就是当是同类的时候 也要union 3对点
还有一个容易漏的是 因为是三角循环 除XY另外一个类也要进行操作
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f #define N 100000+5 int f[3*N]; int find1(int x) { return x==f[x]?x:f[x]=find1(f[x]); } void union1(int a,int b) { int x=find1(a); int y=find1(b); if(x!=y) f[x]=y; } int main() { int n,m; RII(n,m); rep(i,1,3*n)f[i]=i; int cnt=0; rep(i,1,m) { int a,b,c; RIII(a,b,c); if( b>n||c>n||(a==2&&b==c)) { cnt++;continue; } if(a==1) { if(find1(n+c)==find1(b)||find1(2*n+c)==find1(b)) { cnt++;continue; } union1(b,c); union1(b+n,c+n); union1(b+2*n,c+2*n); } else if(a==2) { if(find1(2*n+b)==find1(c)||find1(b)==find1(c)) { cnt++;continue; } union1(n+b,c); union1(2*n+c,b); union1(n+c,2*n+b); } } printf("%d ",cnt); return 0; }