poj1182 食物链 (并查集)

来源:互联网 发布:知学学院于鲁 编辑:程序博客网 时间:2024/05/01 11:17

 

//poj1182 并查集  
//题目意思:有三种动物A,B,C。A吃B,B吃C,c吃A。给出一系列说法,判断错误个数。

//小菜在这道并查集入门题卡了很久啊,终于下定决心把它啃掉。
//原来要记录一下当前动物与根的关系。在给出的两种动物中的根不相同时要进行树的合并。
//若两动物根相同可以根据它们与根的关系去判断。

//代码如下:

 

#include<iostream>#include<cstdio>using namespace std;int path[50002],relation[50002];void makeset ( int x){relation [x] = 0;path[x ] = x;}int findset ( int x){if(x!=path[x]){int temp=path[x];path[x]=findset(path[x]);//这里依然用递归并压缩路径relation[x]=(relation[x]+relation[temp])%3;//根结点变了嘛,要更新一下关系,这个步骤很关键}return path[x];}void unionset ( int px,int py,int d){path[px]=py;//把根py当作px的根relation[px]=d;}int main(){int n,cas;scanf("%d%d",&n,&cas);//这里不用while,不然就wa,我就wa了n次int cnt=0;int i,j;for(i=1;i<=n;i++)makeset(i);for(j=0;j<cas;j++){int d,x,y;scanf("%d%d%d",&d,&x,&y);if(x>n||y>n){cnt++;continue;}if(d==2&&x==y){cnt++;continue;}int px=findset(x),py=findset(y);if(px!=py)//还没联系,“并”操作{unionset(px,py,(relation[y]-relation[x]+2+d)%3);//这里为什么是 relation[y]-relation[x]+2+d 呢,这就要找一下规律了//这里relation[x]==0时,表示x与根同类,等于1时表示 x吃根,2就是 根吃x;}else {if(d==1){if(relation[x]!=relation[y])//表示不是同类cnt++;}else{if(relation[x]!=(relation[y]+1)%3)//表示x吃不了ycnt++;}}}printf("%d\n",cnt);return 0;}