为了账号安全,请及时绑定邮箱和手机立即绑定

并查集——食物链(poj1182)

标签:
算法

题目链接:

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;}


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消