zoukankan      html  css  js  c++  java
  • POJ 1182

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
    现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
    有人用两种说法对这N个动物所构成的食物链关系进行描述:
    第一种说法是"1 X Y",表示X和Y是同类。
    第二种说法是"2 X Y",表示X吃Y。
    此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
    1) 当前的话与前面的某些真的话冲突,就是假话;
    2) 当前的话中X或Y比N大,就是假话;
    3) 当前的话表示X吃X,就是假话。
    你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。

    Input

    第一行是两个整数N和K,以一个空格分隔。
    以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
    若D=1,则表示X和Y是同类。
    若D=2,则表示X吃Y。

    Output

    只有一个整数,表示假话的数目。

    Sample Input

    100 7
    1 101 1
    2 1 2
    2 2 3
    2 3 3
    1 1 3
    2 3 1
    1 5 5

    Sample Output

    3

    题目大意:
    给出n种动物和k句话,判断当前的话是否有矛盾,最后输出假话的数量。
    解题思路:
    很经典的一道种类并查集问题。可以想象成一个环,A->B B->C C->A 表示三种动物的关系,我们用当前的 x 表示动物种类,用 x和y+n 建立关系表示 x 可以吃掉 y+n(A吃B) ,用 x+n 和 y+2n表示x+n吃y+2n (B吃C)用x+2n 和 y 建立关系表示y可以吃掉x+2n(C吃A),形成一个环,这样表示关系就很显而易见了。初始化一下并查集,每个节点都初始化为自己,输入以后先判断一下是否在范围内,(0<x,y<=n)还有本身的逻辑错误,比如 2 3 3 表示3可以吃掉3,显然这是不可以的。AC代码:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int _max = 5e4+50;
    int f[4*_max];//最大需要3*n的空间,数组开大些
    int find(int x)//寻根+路径压缩
    {
    	return f[x]==x?x:f[x]=find(f[x]);
    }
    void merge(int x,int y)//合并操作,将y合并到x
    {
    	f[find(y)]=find(x);
    }
    int main()
    {
    	int n,k,ans=0;
    	cin>>n>>k;
    	for(int i=0;i<=3*_max;i++)
    	  f[i]=i;
    	while(k--)
    	{
    		int d,x,y;
    		scanf("%d%d%d",&d,&x,&y);//PS:这里cin超时
    		if(x>n||y>n||x==0||y==0||(d==2&&x==y))//判断本身是否有错误
    		{
    			ans++;
    			continue;
    		}
    		if(d==1)//表示x和y是同类
    		{
    			if(find(x)==find(y+n)||find(x)==find(y+2*n))//如果x和y+n有关系或者x和y+2*n有关系则说明这是假话
    			{
    				ans++;
    				continue;
    			}
    			merge(x,y);//如果是真话则把x y   x+n  y+n   x+2*n  y+2*n合并一下
    			merge(x+n,y+n);
    			merge(x+2*n,y+2*n);
    		}
    		else//表示x吃y
    		{
    			if(find(x)==find(y)||find(x)==find(y+2*n))//如果 x和y同类或者y吃x则是假话
    			{
    				ans++;
    				continue;
    			}
    			merge(x,y+n);//形成一个环,x 吃 y x+n吃y+2*n x+2*n被y吃
    			merge(x+n,y+2*n);
    			merge(x+2*n,y);
    		}
    	}
    	cout<<ans<<endl;
    	//system("pause");
    	return 0;
    }
    
  • 相关阅读:
    Codeforces 834D The Bakery
    hdu 1394 Minimum Inversion Number
    Codeforces 837E Vasya's Function
    Codeforces 837D Round Subset
    Codeforces 825E Minimal Labels
    Codeforces 437D The Child and Zoo
    Codeforces 822D My pretty girl Noora
    Codeforces 799D Field expansion
    Codeforces 438D The Child and Sequence
    Codeforces Round #427 (Div. 2) Problem D Palindromic characteristics (Codeforces 835D)
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294263.html
Copyright © 2011-2022 走看看