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;
    }
  • 相关阅读:
    在WCF中使用Flag Enumerations
    WCF开发教程资源收集
    [转]WCF 4 安全性和 WIF 简介
    Asp.Net Web API 2 官网菜鸟学习系列导航[持续更新中]
    Asp.Net Web API 2第十八课——Working with Entity Relations in OData
    Asp.Net Web API 2第十七课——Creating an OData Endpoint in ASP.NET Web API 2(OData终结点)
    Asp.Net Web API 2第十六课——Parameter Binding in ASP.NET Web API(参数绑定)
    Asp.Net Web API 2第十五课——Model Validation(模型验证)
    函数 生成器 生成器表达式
    函数的进阶
  • 原文地址:https://www.cnblogs.com/Blackops/p/5766264.html
Copyright © 2011-2022 走看看