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;
    }
    

      

     

  • 相关阅读:
    POJ1321 棋盘问题
    HDU1234 开门人和关门人(解法二)
    HDU1234 开门人和关门人(解法二)
    HDU1996 汉诺塔VI
    HDU1996 汉诺塔VI
    HDU1013 POJ1519 Digital Roots(解法二)
    HDU1013 POJ1519 Digital Roots(解法二)
    HDU4548 美素数
    HDU4548 美素数
    POJ3751 时间日期格式转换【日期计算】
  • 原文地址:https://www.cnblogs.com/ruanmowen/p/12726837.html
Copyright © 2011-2022 走看看