题目链接:
http://poj.org/problem?id=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
解题思路:首先,对并查集不了解的同学请移步http://blog.csdn.net/sm9sun/article/details/53256232
题目中,有捕猎关系和“同一种”关系。
可以通过给每个动物i创建3个元素x-A,x-B,x-C,分别进行维护。
如果x-A与y-B为同一组,那么就代表 动物x为A种类且动物y为B种类。
所以,对上面两种信息,我们可以分别管理他们的连接关系与连接属性f表示动物关系指向,g表示关系类型
/*并查集构造关系,假设f[A]=B:
g[A]=0A与B同类;
g[A]=1B可以吃A;
g[A]=2A可以吃B。
*/
再把归纳方法枚举出来即可
#include<stdio.h>/*并查集构造关系,假设f[A]=B:g[A]=0A与B同类;g[A]=1B可以吃A;g[A]=2A可以吃B。*/ /*这个坑爹测试数据 不能加while输入 */ int f[50500];int g[50500];int c(int x){if(x==f[x]) return x;int fx=f[x];f[x]=c(f[x]);g[x]=(g[x]+g[fx])%3;return f[x];}int pd(int x,int y,int p) {int a=c(x),b=c(y);if(a==b){if(p==1&&g[x]!=g[y])return 1;if(p==2){if(g[x]==2&&g[y]!=1)return 1;if(g[x]==1&&g[y]!=0)return 1;if(g[x]==0&&g[y]!=2)return 1;}return 0;}f[a]=b;if(p==2)g[a]=(g[y]-g[x]+3+1)%3;else g[a]=(g[y]-g[x]+3)%3;return 0;}int main(){int n,k;int i,sum;int p,x,y;scanf("%d%d",&n,&k);for(i=1;i<=n;i++){ f[i]=i;g[i]=0; }sum=0; while(k--) { scanf("%d%d%d",&p,&x,&y); if(x>n||y>n||(x==y&&p==2))sum++;else if(pd(x,y,p))sum++;}printf("%d\n",sum);return 0;}
共同学习,写下你的评论
评论加载中...
作者其他优质文章