poj 1182 (关系并查集) 食物链

题目传送门:http://poj.org/problem?id=1182

这是一道关系型并查集的题,对于每个动物来说,只有三种情况:同类,吃与被吃;

所以可以用0,1,2三个数字代表三种情况,在使用并查集的时候再多加一个关系数组,初始时全部赋值为0

然后就是在进行并查集的每一步时加入关系的改变,

如果祖先节点相同,说明两者之间的关系已经出现,是已知的,判断两者关系之和与给的d-1是否相同

祖先节点不同,说明在此之前两者的关系还未知,就赋予关系

噢 对了 poj 上的这题要单组输入,多组会wa

code

 

 1 #include<cstdio>

 2 using namespace std;

 3 int father[50005];

 4 int relat[50005];

 5 void give (int n)

 6 {

 7     for (int i=1;i<=n;i++)

 8     {

 9         father[i]=i;

10         relat[i]=0; //初始关系都为0

11     }

12 }

13 int find(int x)

14 {

15     if (x==father[x]) return father[x];

16     int t=find(father[x]);

17     relat[x]=(relat[x]+relat[father[x]])%3; //在寻找祖先节点的过程中也要更新关系

18     father[x]=t;

19     return father[x];

20 }

21 int main()

22 {

23     int n,k,sum,d,x,y,sx,sy;

24     scanf("%d %d",&n,&k);

25     give(n);

26     sum=0;

27     while (k--)

28     {

29         scanf("%d %d %d",&d,&x,&y);

30         if (x>n||y>n)

31         {

32             sum++;

33             continue;

34         }

35         if (d==2&&x==y) //不能自己吃自己啊

36         {

37             sum++;

38             continue;

39         }

40         sx=find(x);

41         sy=find(y);

42         if (sx==sy) //说明关系可以确定,因为在之前出现过

43         {

44             if ((relat[x]-relat[y]+3)%3!=d-1)  //加三为了避免负数

45               sum++;

46         }

47         else    //关系还不确定,那么不能判断,只能赋予关系

48         {

49             father[sx]=sy;

50             relat[sx]=(relat[y]-relat[x]+3+d-1)%3;  //sx,sy,x,y的顺序不要反了,这都是对应的

51         }

52     }

53     printf("%d\n",sum);

54     return 0;

55 }

 

你可能感兴趣的:(poj)