E - 食物链 (拆点并查集)
题目链接:https://vjudge.net/contest/339425#problem/E
思路:
这题原来做的时候用的是种类并查集,但是我忘了。
现在有一个更玄学的做法
因为说白了就是A B C 三个点之间的关系
那么我就把一个点拆成三个点(也就是开三倍的空间) 分别代表这个点是A B C
然后这个题就成了模拟???
1 #include <math.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <iostream> 5 #include <algorithm> 6 #include <string> 7 #include <string.h> 8 #include <vector> 9 #include <map> 10 #include <stack> 11 #include <set> 12 //#include <random> 13 14 #define LL long long 15 #define INF 0x3f3f3f3f 16 #define ls nod<<1 17 #define rs (nod<<1)+1 18 const int maxn = 3e5 + 10; 19 const double eps = 1e-9; 20 int pre[maxn]; 21 22 void init(int n) { 23 for (int i=0;i<=n;i++) { 24 pre[i] = i; 25 } 26 } 27 28 int find(int x) { 29 if (pre[x] == x) 30 return x; 31 return pre[x] = find(pre[x]); 32 } 33 34 void merge(int x,int y) { 35 int rootx = find(x),rooty = find(y); 36 pre[rooty] = rootx; 37 } 38 int main() { 39 int n,k; 40 scanf("%d%d",&n,&k); 41 init(3*n); 42 int d,x,y; 43 int ans = 0; 44 for (int i=1;i<=k;i++) { 45 scanf("%d%d%d",&d,&x,&y); 46 if (x > n || y > n) { 47 ans++; 48 continue; 49 } 50 if (d == 1) { 51 if (find(x) == find(y+n) || find(x) == find(y+2*n) ) { 52 ans++; 53 continue; 54 } 55 merge(x,y); 56 merge(x+n,y+n); 57 merge(x+2*n,y+2*n); 58 } 59 if (d == 2) { 60 if (find(x) == find(y) || find(x) == find(y+2*n)) { 61 ans++; 62 continue; 63 } 64 merge(x,y+n); 65 merge(x+n,y+2*n); 66 merge(x+2*n,y); 67 } 68 } 69 printf("%d\n",ans); 70 return 0; 71 }