首页 > 代码库 > poj 1182 食物链 种类并查集

poj 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),输出假话的总数。 

题目的实质就是把给的N个动物划分到3个集合里去。最核心的在于需要实现父亲的父亲的父亲是同类。联想到取余操作。思路就出来了。

技术分享
 1 #include<cstdio>
 2 using namespace std;
 3 const int MAXN=50010;
 4 int fa[MAXN];
 5 int rel[MAXN];   // 0代表同类,1代表吃fa[i],2代表被吃
 6 void _set(int n)
 7 {
 8     for(int i=1;i<=n;i++)
 9     {
10         fa[i]=i;
11         rel[i]=0;
12     }
13 }
14 int _find(int k)
15 {
16 if(fa[k]!=k)
17 {
18     int t=fa[k];
19     fa[k]=_find(fa[k]);
20     rel[k]=(rel[k]+rel[t])%3;
21 }
22 return fa[k];
23 }
24 void _union(int x,int y,int d)
25 {
26     int fx=_find(x);
27     fa[fx]=y;
28     rel[fx]=(d-1-rel[x]+3)%3;
29 }
30 int relation(int x,int y,int root)
31 {
32     return (rel[x]-rel[y]+3)%3;
33 }
34 int main()
35 {
36    // freopen("in.txt","r",stdin);
37    // freopen("out.txt","w",stdout);
38     int n,d,x,y,fx,fy;
39     long int k,ans;
40     ans=0;
41     scanf("%d %ld",&n,&k);
42     _set(n);
43     for(long int i=1;i<=k;i++)
44     {
45         scanf("%ld %ld %ld",&d,&x,&y);
46         if(x>n||y>n)
47         {
48             ans++; //printf("1: %d %d %d\n",d,x,y);
49             continue;
50 
51         }
52         if(d==2&&x==y)
53         {
54             ans++;
55            // printf("2: %d %d %d\n",d,x,y);
56             continue;
57 
58         }
59         fx=_find(x);
60         fy=_find(y);
61         if(fx!=fy)
62         {
63             _union(x,y,d);
64         }
65         else
66         {
67             if(d-1!=relation(x,y,fx))
68             {
69                 ans++;
70               //  printf("3: %d %d %d %d\n",d,x,y,relation(x,y,fx));
71             }
72         }
73     }
74     printf("%ld",ans);
75     return 0;
76 }
View Code

 

poj 1182 食物链 种类并查集