poj1182食物链(详细解答)
描述:
现有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),输出假话的总数。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
output

主要涉及压缩后的关系的修正:枚举发现有以下规律:
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 }

浙公网安备 33010602011771号