zoukankan      html  css  js  c++  java
  • POJ 1182 食物链(种类并查集)

    食物链
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 63592   Accepted: 18670

    Description

    动物王国中有三类动物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

    Source

    题目链接:POJ 1182

    这题困扰了我很久,也一直不敢去做,因为看了很多的题解,都看不懂在讲什么,今天又拿出题解看了一下,总算是看懂一点门道了,先上大牛博客:POJ 1182题解

    然后一定要在纸上画出这个题解中的所有关系的向量箭头,其实说是向量相加,其实还是用数字加的,只是确实非常神奇地符合向量的相加结果(大牛的思想本渣还未完全明白)。

    我也就再在大牛们的题解基础上写一下我的理解,也许能帮助更多的人理解这个意思。

    首先按照题解中给出的关系进行一 一对应,即我们设的关系就是要跟(D-1)这个值一致。

    先排除掉最简单的两种假话:比范围N大以及自己吃自己。

    然后考虑另外的情况即要开始检验两者关系是否如题目所给出的D那样;

    显然当两者原本就没有关系的时候,无论D是1或2,都是真话,那这些话有什么用呢,就是给之后的假话铺垫制造制约条件。当然对于这些话的处理就是要合并(在此题这种分组并查集的写法中同一个集合就不是指同一个物种了,只要两者存在捕食关系都会在同一个集合里,比如1吃2,2吃3,3吃1,那1、2、3都会在同一个集合里,只是谁当根节点的问题)

    然后如何合并呢?你可以任选合并一个方向如Fx并到Fy或Fy并到Fx(选完方向后之后的操作都要一致),但是要遵循祖先并到另一个的祖先这个原则,即原来子代不并,但是把根节点直接接到另一个根节点上去,但是这样一来被合并的根节点关系可以立马得到,但被牵连的子节点怎么办,当然就是要用路径压缩进行更新,为什么要更新,合并之后父亲节点都已经变化了,当然要更新,如何更新相信题解讲的很清楚。

    然后就是解法中说的x->y这个东西,你要自己在纸上对x->y连一条方向线,我原来找半天不知道x->y在哪,感觉根本无法得知啊,然后发现x->y其实就是题中所给关系即D-1……(如果你画的没错的话第一个情况是一个四边形,第二种是一个三角形,箭头与node.relation千万别搞错)

    其次就是那个向量公式里有几处可能写的比较难懂,箭头就是指向量,然后几个公式都有+3,是因为要正向取模,个人认为+3应该放到最后而不是中间。然后自己也靠着画的图和理解写了一份比较清晰的代码(绝对不是某些大牛的杀马特风格)用PPT简单地做了两张图,希望没错………


    最后这题还有一个有毒的地方,不要用while(scanf(......)!=EOF),会WA

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<sstream>
    #include<cstring>
    #include<bitset>
    #include<cstdio>
    #include<string>
    #include<deque>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define CLR(x,y) memset(x,y,sizeof(x))
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    typedef pair<int,int> pii;
    typedef long long LL;
    const double PI=acos(-1.0);
    const int N=50010;
    struct info
    {
    	int rela;
    	int pre;
    };
    info node[N];
    void init()
    {
    	for (int i=0; i<N; ++i)
    	{
    		node[i].rela=0;
    		node[i].pre=i;
    	}
    }
    int find(int n)
    {
    	if(n==node[n].pre)
    		return n;
    	else
    	{
    		int tpre;
    		tpre=node[n].pre;
    		node[n].pre=find(node[n].pre);
    		node[n].rela=(node[n].rela+node[tpre].rela)%3;
    		return node[n].pre;
    	}
    }
    int main(void)
    {
    	int n,k,i,x,y,d;
    	scanf("%d%d",&n,&k);
    	init();
    	int lie=0;
    	for (i=0; i<k; ++i)
    	{
    		scanf("%d%d%d",&d,&x,&y);
    		if(x>n||y>n)
    			lie++;
    		else if(d==2&&x==y)
    			lie++;
    		else
    		{
    			int fx=find(x),fy=find(y);
    			if(fx!=fy)//根不同即此时无关系,不可能会有假话,先并掉 
    			{
    				node[fy].pre=fx;
    				node[fy].rela=(node[x].rela+(d-1)-node[y].rela+3)%3;					
    			}
    			else//根相同,这才是可能出假话的地方  
    			{
    				if(d==1)//这里两个判断是可以统一的,完全可以把if和if-else合在一起
    				{
    					if(d-1!=(node[y].rela-node[x].rela+3)%3)
    					//这里为了清晰写成跟下面一样的公式,其实用node[y].rela!=node[x].rela也是可以的
    						lie++;
    				}
    				else if(d==2)
    				{
    					if(d-1!=(node[y].rela-node[x].rela+3)%3)
    						lie++;
    				}
    			}
    		}
    	}
    	printf("%d
    ",lie);
    	return 0;
    }
  • 相关阅读:
    【leetcode】1403. Minimum Subsequence in Non-Increasing Order
    【leetcode】1399. Count Largest Group
    【leetcode】1396. Design Underground System
    【leetcode】1395. Count Number of Teams
    【leetcode】1394. Find Lucky Integer in an Array
    【leetcode】1391. Check if There is a Valid Path in a Grid
    【leetcode】1390. Four Divisors
    【leetcode】1389. Create Target Array in the Given Order
    modelsim仿真基本流程
    Quartus调用MOdelsim仿真过程
  • 原文地址:https://www.cnblogs.com/Blackops/p/5766264.html
Copyright © 2011-2022 走看看