题目描述
动物王国中有三类动物 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 中
一行,一个整数,表示假话的总数。
输入输出样例
输入 #1
100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5
输出 #1
3
说明/提示
1 ≤ N ≤ 5 ∗ 10^4
1 ≤ K ≤ 10^5
思路
换了和之前不同的种类并查集来解决此类问题,用n 2n 3n 三个集合来表明不同的关系;
n为平等集合, 2n为生产者集合, 3n为捕食者集合.
根据题意给出的不同关系加入不同的并查集.
CODE
1 #include <bits/stdc++.h> 2 #define dbg(x) cout << #x << "=" << x << endl 3 #define eps 1e-8 4 #define pi acos(-1.0) 5 6 using namespace std; 7 typedef long long LL; 8 9 template<class T>inline void read(T &res) 10 { 11 char c;T flag=1; 12 while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; 13 while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; 14 } 15 16 namespace _buff { 17 const size_t BUFF = 1 << 19; 18 char ibuf[BUFF], *ib = ibuf, *ie = ibuf; 19 char getc() { 20 if (ib == ie) { 21 ib = ibuf; 22 ie = ibuf + fread(ibuf, 1, BUFF, stdin); 23 } 24 return ib == ie ? -1 : *ib++; 25 } 26 } 27 28 int qread() { 29 using namespace _buff; 30 int ret = 0; 31 bool pos = true; 32 char c = getc(); 33 for (; (c < '0' || c > '9') && c != '-'; c = getc()) { 34 assert(~c); 35 } 36 if (c == '-') { 37 pos = false; 38 c = getc(); 39 } 40 for (; c >= '0' && c <= '9'; c = getc()) { 41 ret = (ret << 3) + (ret << 1) + (c ^ 48); 42 } 43 return pos ? ret : -ret; 44 } 45 46 const int maxn = 2e5 + 7; 47 48 int fa[maxn]; 49 int n,k; 50 51 int fid(int x) { 52 return x == fa[x] ? x : fid(fa[x]); 53 } 54 55 void init() { 56 for ( int i = 1; i <= 3 * n; ++i ) { 57 fa[i] = i; 58 } 59 } 60 61 int main() 62 { 63 scanf("%d %d",&n, &k); 64 init(); 65 int ans = 0; 66 for ( int i = 1; i <= k; ++i ) { 67 int x, y, opt; 68 scanf("%d %d %d",&opt, &x, &y); 69 if(x > n || y > n) { 70 ans++; 71 continue; 72 } 73 if(opt == 1) { 74 if(fid(x) == fid(y + n) || fid(x + n) == fid(y)) { 75 ans++; 76 continue; 77 } 78 fa[fid(x)] = fid(y); 79 fa[fid(x + n)] = fid(y + n); 80 fa[fid(x + 2 * n)] = fid(y + 2 * n); 81 } 82 else if(opt == 2) { 83 if(fid(x) == fid(y) || fid(x) == fid(y + n)) { 84 ans++; 85 continue; 86 } 87 fa[fid(x + n)] = fid(y); 88 fa[fid(x)] = fid(y + 2 * n); 89 fa[fid(x + 2 * n)] = fid(y + n);//捕食者集合连生产者集合 90 } 91 } 92 cout << ans << endl; 93 return 0; 94 }