zoukankan      html  css  js  c++  java
  • Poj1182 食物链(并查集/带权并查集)

    题面

    Poj

    题解

    这里采用并查集的补集。

    $x$表示同类集合,$x+n$表示敌人集合,$x+n imes2$表示敌人的敌人集合。

    如果当前给出的是一对同类关系,就判断$x$是否吃$y$或者$y$是否吃$x$(冲突)。

    如果是真话,就将所有关系连在一起。

    反之,如果给出的是一对$x$吃$y$关系,就判断$x$是否吃了自己(矛盾)或者他们两个互相吃(冲突)。

    如果是真话,将$x$的敌人和$y$的敌人的敌人(朋友)连在一起,将$y$的敌人和$x$的敌人的敌人(朋友)连在一起,即$y$的敌人是$x$的朋友,将$y$丢进$x$的敌人集合中。

    上面这对话可能有点绕口,但是大概还是讲出来了,仔细理解一下吧...

    这里还有一个带权并查集的做法,但是并查集补集更好写(写起来更顺些)。

    #include <cstdio>
    #include <cstring>
    #define Rg register 
    
    const int N = 5e4 + 10;
    int n, k, fa[N * 3], cz, x, y, ans, nn;
    
    int find (int x) {
    	if (fa[x] != x) fa[x] = find (fa[x]);
    	return fa[x];
    }
    
    int unionn (int u, int v) {
    	int fu = find (u), fv = find (v);
    	fa[fv] = fu;
    }//v -> u
    
    int main () {
    	scanf ("%d%d", &n, &k);
    	nn = n * 3;
    	for (Rg int i = 1; i <= nn; ++i)
    		fa[i] = i;
    	while (k--) {
    		scanf ("%d%d%d", &cz, &x, &y);
    		if (x > n || y > n) {++ans; continue;}//依据2
    		if (cz == 1) {
    			if (find (x + n) == find(y) || find (y + n) == find (x)) {++ans; continue;}//依据1
    			unionn (x, y); unionn (x + n, y + n); unionn (x + (n << 1), y + (n << 1));
    		} else {
    			if (find (x) == find (y) || find (x) == find (y + n)) {++ans; continue;}//依据1&依据3
    			unionn (y + (n << 1), x); unionn (y, x + n); unionn (y + n, x + (n << 1));
    		}
    	}
    	printf ("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    ubuntu下无法在目录下创建文件夹,权限不足解决办法
    mongo中的模糊查询
    mysql中的模糊查询
    mysql安装与配置详情
    Django model中的class Meta详解
    kafka集群搭建
    myeclipse/eclipse添加Spket插件实现ExtJs4.2/ExtJs3智能提示
    博客园自定义标题、阅读目录、导航栏、活动的推荐&反对按钮
    IntelliJ IDEA 14 创建maven项目二
    EXT4.2--Ext Designer 使用
  • 原文地址:https://www.cnblogs.com/water-mi/p/10303467.html
Copyright © 2011-2022 走看看