poj1182食物链(详细解答)

描述:

动物王国中有三类动物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和K,以一个空格分隔。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y
 
输出:
只有一个整数,表示假话的数目。
 
eg:
input   
      100 7
      1 101 1
      2 1 2
      2 2 3
      2 3 3
      1 1 3
      2 3 1
     1 5 5
output
     3
思路:
  带权并查集的应用。
0 表示 同类 1 表示 父吃子 2 表示 子吃父
输入的d 的转化 d-1
关键两步:
  一、查找(路径压缩)
 

主要涉及压缩后的关系的修正:枚举发现有以下规律:

     i         j         ( i+j)%3

 father    son   son--->root

  0           0            0       

  0           1            1

  0           2            2

  1           0            1

  1           1            2

  1           2            0

  2           0            2

  2           1            0

  2           2             1

即  (son.relation + father.relation )%3=son-->root.relatiion

这个关系很重要,在合并的推导时要用到,需要注意指向。

  二、合并

合并的关键也在于合并时的关系的确定:

   若将 y 合并到 x 上,(d-1)为x,y之间的关系。由图可知,x为y的父节点,rooty为y的儿子节点。

由y与根节点rooty的关系(绿颜色)逆推根节点rooty与y的关系为 3-y.relation    (方向)

        由查找中的推导知(rooty-->>y-->>x 符合)rooty与x之间的关系为

         (3-y.relation+(d-1))%3         (方向)

从而推导出rootx 与rooty 之间的关系为

         ((3-y.relation+(d-1))%3+x.relation)%3

也即

        (3-y.relation+(d-1)+x.relation)%3           (同余定理)

规律推导到此结束

三、问题的解答

  判断:if (x,y 在同一集合中)then 合并

         else if(x.relaton!=y.relation)--->>假话             (d==1)

 

         if (x,y不在同一集合) then 合并

        else  if((3-x.relation+y.relation)%3!=1) --->>假话  (d==2)

     说明:x,y在同一集合时,根节点相同。

   注:(3-x.relation+y.relation)%3!=1 也是参照查找的规律。(绿线表示判断d==2)

           注:poj上只有一组数据,多组数据会WA。

                读入d x y 用cout 会超时。

View Code
 1 #include<iostream>
 2 using namespace std;
 3 struct animal
 4 {
 5  int parent;
 6  int relation;
 7 }ani[50005];
 8 
 9 void init_Animal(int n)
10 {  
11     for(int i = 1 ; i <= n ; i++)  
12     {  
13         ani[i].parent = i;  
14         ani[i].relation = 0;  //0 同类 1 父吃子 2 子吃父
15     }  
16 } 
17 
18 int find(int x)//查找
19 {
20     int temp;
21   if(ani[x].parent==x)
22       return x;
23     temp=ani[x].parent;
24     ani[x].parent=find(temp);//指向根节点                                                   //路径压缩
25     ani[x].relation=(ani[temp].relation+ani[x].relation)%3; //修正关系            //更新压缩后的关系域
26     return ani[x].parent;      
27 }
28 void union_set(int x,int fx,int y,int fy,int d)
29 {
30      ani[fy].parent=fx;                                              //合并集合
31      ani[fy].relation=(3+(d-1)+ani[x].relation-ani[y].relation)%3;    //更新原来集合关系域
32 }
33 int main()
34 {
35   int N,K,i,d,x,y,ans,fx,fy;
36   //while(cin>>N>>K)
37   //{
38   cin>>N>>K;
39      init_Animal(N);
40      ans=0;
41      for(i=0;i<K;i++)
42      {
43        // cin>>d>>x>>y;
44            scanf("%d%d%d",&d,&x,&y);
45         if(x>N||y>N) 
46             ans++;         
47         else
48         {
49             if(d==2&&x==y)
50                 ans++;
51             else
52             {
53                   fx=find(x);
54                   fy=find(y);
55                   if(fx!=fy)
56                       union_set(x,fx,y,fy,d);
57                   else
58                   {
59                        switch(d)
60                        {
61                            case 1:
62                                { 
63                                    if(ani[x].relation!=ani[y].relation)
64                                        ans++;
65                                    break;
66                                }
67                            case 2:
68                                {
69                                    if((3-ani[x].relation+ani[y].relation)%3!=1)
70                                        ans++;
71                                    break;
72                                }
73                        }
74                   }
75             }
76         }
77      }
78      cout<<ans<<endl;
79   //}
80 return 0;
81 }

 

 

  

posted on 2012-05-11 17:55  L_S_X  阅读(241)  评论(0)    收藏  举报

导航