种类并查集
食物链
https://ac.nowcoder.com/acm/problem/16884
传送门
食物链
题意:
有三种动物,其食物链形成一个环,即A吃B,B吃C,C吃D。
现在有n个动物,每个动物都属于ABC中的一种,给你k个描述,判断这k种描述的真假,求出假话的总数。
每次描述输入三个数字d,x, y。
d = 1时,表示X和Y是同类
d = 2时,表示X吃Y
思路:
对于每个动物,都有三种可能,可能是A,可能是B,可能是C
所以我们开三倍的数组,将一个数组分成三份来判断——1 到 n是假设一,n + 1 到n * 2是假设二,n * 2 + 1 到 n * 3是假设三
1A 2A 3A
1B 2B 3B
1C 2C 3C
假设1是A
当d=1时,说明2和1是同类,则2就是A。
我们只需要判断1A和2A是不是同类即可
当d=2时,说明1吃2,根据题意,A吃B,所以2是B。
我们只需要判断1A和2B是不是同类即可
假设1是B
当d=1时,说明2和1是同类,则2就是B
我们就判断1B和2B是不是同类即可
当d=2时,说明1吃2,根据题意,B吃C,所以2是C
我们只需要判断1B和2C是不是同类即可
假设1是C
当d=1时,说明2和1是同类,则2就是C
我们只需要判断1C和2C是不是同类即可
当d=2时,说明1吃2,根据题意,C吃A,所以2是A
我们只需要判断1C和2A是不是同类即可
所以对于d = 1,说明1和2必须是同类,也就是find(1) = find(2),抽象化一下就是find(x) == find(y) find(x + n) == find(y + n) find(x + n * 2) == find(y + n * 2),我们只需要找到不等的情况,让sum++即可,对于相等的情况来说,就是正确的,我们就把三种情况分别进行合并
对于d = 2,说明1吃2,根据题中的对应关系,抽象化成find(x) = find(y + n),find(x + n) = find(y + n * 2), find(x + n * 2) = find(y),操作同上
#include <cstdio> #include <cstring> #include <string> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <stack> #include <queue> #include <stdlib.h> #include <sstream> #include <map> #include <set> using namespace std; #define inf 0x3f3f3f3f #define MAX 150000 + 5 typedef long long ll ; inline int IntRead(){ char ch = getchar();int s = 0, w = 1; while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0';ch = getchar();} return s * w; } int n, fa[MAX]; //初始化一定要记得是对n * 3 的数进行初始化 void init(){ for(int i = 1; i <= n * 3; ++i) fa[i] = i; } int find(int x){//找根 return x == fa[x] ? x : fa[x] = find(fa[x]); } void emerge(int x, int y) { fa[find(x)] = find(y); } int main() { int d, k ,x, y, sum = 0; cin>>n>>k; init(); for(int i = 1; i <= k; ++i){ cin>>d>>x>>y; if(x > n || y > n){ sum++; continue; } //x 代表x是a,x + n代表x是b, x + 2 * n代表x是c if(d == 1){ if(find(x) == find(y + n) || find(x) == find(y + n * 2)){ sum++; continue; } emerge(x, y);//合并 emerge(x + n, y + n); emerge(x + n * 2, y + n * 2); } else if(d == 2){ if(find(x) == find(y) || find(x) == find(y + n * 2)){ sum++; continue; } emerge(x, y + n); emerge(x + n, y + n * 2); emerge(x + n * 2, y); } } cout<<sum<<endl; return 0; }