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
",sum);
54     return 0;
55 }
原文地址:https://www.cnblogs.com/JJCHEHEDA/p/4676172.html