zoukankan      html  css  js  c++  java
  • P2024 [NOI2001]食物链

    算法

    并查集+扩展域

    思路

     扩展域并查集维护三个域:x_self同类,x_enemy天敌,x_eat捕食。

    他们之间的关系:

    假设有x,y两个动物,

     

    如果题目给定x和y是同类,那么合并x_self,y_self和x_enemy,y_enemy和x_eat和y_eat。

    前提条件是:x_self与y_eat不在同一个集合,x_eat与y_self不在同一个集合。

     

    如果题目给定x吃y,这里我们注意到一点,由于题目给出的食物链关系是环形,因此我们可以由x吃y”推断出“x的天敌是y的猎物

    由此得到,合并x_eat,y_self和x_self,y_enemy和x_enemy,y_eat。

    前提条件是:x_self和y_self不在一个集合,x_self和y_eat不在一个集合。

    代码

    #include <cstdio>
    #include <iostream>
    using namespace std;
    const int N = 50006;
    int fa[3*N];
    
    int get(int x) {
    	if (x == fa[x]) return x;
    	return fa[x] = get(fa[x]);
    }
    
    int main() {
    	int n, k, ans = 0;
    	cin >> n >> k;
    	for (int i = 1; i <= 3 * n; i++) fa[i] = i;
    	while (k--) {
    		int num, x, y;
    		scanf("%d %d %d", &num, &x, &y);
    		if (x > n || y > n || (num == 2 && x == y)) {
    			++ans;
    			continue;
    		}
    		if (num == 1 && (get(x) == get(y + n) || get(x + n) == get(y))) {
    			++ans;
    			continue;
    		}
    		if (num == 2 && (get(x) == get(y) || get(x) == get(y + n))) {
    			++ans;
    			continue;
    		}
    		if (num == 1) {
    			fa[get(x)] = get(y);
    			fa[get(x+n)] = get(y + n);
    			fa[get(x+2*n)] = get(y + 2 * n);
    		} else {
    			fa[get(x+n)] = get(y);
    			fa[get(x+2*n)] = get(y + n);
    			fa[get(x)] = get(y + 2 * n);
    		}
    	}
    	cout << ans << endl;
    	return 0;
    }
    

      

     

  • 相关阅读:
    450. K组翻转链表
    6. 合并排序数组 II
    64. 合并排序数组
    165. 合并两个排序链表
    103. 带环链表 II
    102. 带环链表
    [web安全原理]PHP命令执行漏洞基础
    [原题复现]-HITCON 2016 WEB《babytrick》[反序列化]
    《将博客搬至CSDN》
    PHP反序列化漏洞-CVE-2016-7124(绕过__wakeup)复现
  • 原文地址:https://www.cnblogs.com/ruanmowen/p/12726837.html
Copyright © 2011-2022 走看看