• 【洛谷P2024】食物链【种类并查集】


    题目描述

    动物王国中有三类动物 A , B , C A,B,C A,B,C,这三类动物的食物链构成了有趣的环形。 A A A B B B B B B C C C C C C A A A

    现有 N N N 个动物,以 1 ∼ N 1 \sim N 1N 编号。每个动物都是 A , B , C A,B,C A,B,C 中的一种,但是我们并不知道它到底是哪一种。

    有人用两种说法对这 N N N 个动物所构成的食物链关系进行描述:

    • 第一种说法是 1 X Y,表示 X X X Y Y Y 是同类。
    • 第二种说法是2 X Y,表示 X X X Y Y Y

    此人对 N N N 个动物,用上述两种说法,一句接一句地说出 K K K 句话,这 K K K 句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

    • 当前的话与前面的某些真的话冲突,就是假话;
    • 当前的话中 X X X Y Y Y N N N 大,就是假话;
    • 当前的话表示 X X X X X X,就是假话。

    你的任务是根据给定的 N N N K K K 句话,输出假话的总数。

    输入格式

    第一行两个整数, N , K N,K N,K,表示有 N N N 个动物, K K K 句话。
    第二行开始每行一句话(按照题目要求,见样例)

    输出格式

    一行,一个整数,表示假话的总数。

    样例输入 #1

    100 7
    1 101 1
    2 1 2
    2 2 3
    2 3 3
    1 1 3
    2 3 1
    1 5 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    样例输出 #1

    3
    
    • 1

    提示

    对于全部数据, 1 ≤ N ≤ 5 × 1 0 4 1\le N\le 5 \times 10^4 1N5×104 1 ≤ K ≤ 1 0 5 1\le K \le 10^5 1K105

    分析

    有了并查集可以表示元素是否在同一个集合的关系,于是可以拓展到种类并查集,就是将元素“复制”一遍然后放在另一个类中,表示敌人,比如,分A,B类,如果A中元素与B中元素合并,那么这两个就是敌人。

    对于这道题,可以开一个三类并查集,一个元素有三个域, x x x表示同类, x + n x+n x+n表示猎物, x + 2 n x+2n x+2n表示天敌,对于每句话,只需要先判断正确与否(用矛盾关系,比如判断x是不是y的猎物只需要看father(x)==father(y+n),然后再设置关系状态,合并操作就可以完成。

    上代码

    #include
    #include
    #include
    using namespace std;
    
    int n,k,fa[150010],ans;//x本身,x+n猎物,x+2n天敌 
    
    int father(int x)
    {
    	if(fa[x]==x) return x;
    	else return fa[x]=father(fa[x]);
    }
    
    void hb(int x,int y)
    {
    	int fx=father(x);
    	int fy=father(y);
    	fa[fx]=fy;
    }
    
    int main()
    {
    	cin>>n>>k;
    	for(int i=1;i<=3*n;i++) fa[i]=i;
    	for(int i=1;i<=k;i++)
    	{
    		int d,x,y;
    		scanf("%d%d%d",&d,&x,&y);
    		if(x>n||y>n)
    		{
    			ans++;
    			continue;
    		}
    		if(d==1)
    		{
    			if(father(x+n)==father(y)||father(x+2*n)==father(y))
    			{
    				ans++;continue;
    			}
    			hb(x,y);hb(x+n,y+n);hb(x+2*n,y+2*n);
    		}
    		else
    		{
    			if(father(x+2*n)==father(y)||father(x)==father(y))
    			{
    				ans++;continue; 
    			}
    			hb(x,y+2*n);hb(x+n,y);hb(x+2*n,y+n);
    		}
    	}
    	cout<<ans;
    	return 0;
     } 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
  • 相关阅读:
    【原创】java+jsp+servlet简单图书管理系统设计与实现
    用Python写MapReduce函数——以WordCount为例
    钡铼BL124EC实现EtherCAT转Ethernet/IP的优势
    【pygame游戏】用Python实现一个蔡徐坤大战篮球的小游戏,可还行?【附源码】
    手敲,Ascend算子开发入门笔记分享
    AI助力快速定位数据库难题
    数据结构与算法----详解二叉树的遍历(迭代、递归)
    Spring Data JPA
    Python urllib, urllib2, urllib3 以及 requests 的区别 (附个人一些看法)
    从零入门激光SLAM(十一)——LeGo-LOAM源码超详细解析1
  • 原文地址:https://blog.csdn.net/dglyr/article/details/126282056