题目链接:点我
Input
第一行是两个整数N和K,以一个空格分隔。 以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 若D=1,则表示X和Y是同类。 若D=2,则表示X吃Y。Output
只有一个整数,表示假话的数目。Sample Input
100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5Sample Output
3题意:
中文题目,题意很清晰,
思路:
带权并查集或者分组并查集都可以做,这里我用的分组并查集,
我们开三个并查集来维护三类动物之间的关系,每次加入之前先判断是否冲突,然后将他们加入并查集,并且加入的时候我们要加入三次,具体请看代码注释,
代码:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> using namespace std; const int maxn = 50000 * 3 + 10; int f[maxn]; int getf(int x){ if(f[x] == x) return x; return f[x] = getf(f[x]); } void Merge(int x, int y){ int t1 = getf(x); int t2 = getf(y); if(t1 != t2){ f[t2] = t1; } } int main(){ int n, k; scanf("%d %d", &n, &k); for(int i = 1; i <= n+n+n; ++i) f[i] = i; int ans = 0; while(k--){ int d, x, y; scanf("%d %d %d", &d, &x, &y); if(x > n || y > n || (d ==2 && x == y)){ ++ans; continue; } if(d == 1){ if(getf(x)==getf(y+n)||getf(x)==getf(y+n+n)) ++ans;//判断他们是否构成吃与被吃的关系 else { Merge(x,y);//他们是同类,所以加入一组并查集中, Merge(x + n, y + n); Merge(x + n + n, y + n + n); } }else { if(getf(x) == getf(y)||getf(x)==getf(y+n+n)) ++ans;//判断是否 x 与 y构成同类或者 反吃的情况 else { Merge(x,y+n);//A 吃 B Merge(x+n,y+n+n);//B 吃 C Merge(x+n+n,y);//C 吃 A } } } printf("%d\n",ans); return 0; }