種類並查集


E - A Bug's Life POJ - 2492

D - Find them Catch them

E - 食物鏈 POJ - 1182

種類並查集總歸一個思想,就是把一堆的東西分為一些種類,但實際上,每個東西的種類並不確定,強行給它確定一個種類的會不好處理,因為它本身的不確定性。但是如果把他們歸到一個集合里,有一個共同的根節點,當要判斷某兩個東西的關系時,就可以根據他們跟根節點的關系判斷。就以食物鏈這題舉例。

題目大意就是,三類動物A吃B,B吃C,C吃A這么一個食物鏈,然后是有一堆動物並不確定他們是哪類動物,有個人說它們之間的關系,然后判斷這個人說的假話有多少句。

跟之前的思路,真話就它們歸到一個根節點,而它們和根節點的關系有3種同類,吃,被吃,關鍵的處理就在於路徑壓縮以及和根節點的關系,還有判定是不是假話。假如就設定一個動物和它根節點的關系為,0跟根節點同類 1被根節點吃 2吃根節點,那么在路徑壓縮時,

假如根節點是A,那么A<--B<--C,那么A<--C的關系是?通過觀察可以發現00->0 01->1 02->2 10->1 11->2 12->0 20->2 21->0 22->1,C與A的關系是由C與B的關系還有B與A的關系決定的,在這個問題中就有,當前點與根節點關系=(當前點與目前的上一節點的關系+目前的上一節點與根節點關系)%3 。

那在兩個動物的根節點連接在一起時該怎么確定,其中一方跟根節點的關系呢?這就需要向量加法假設B是根節點是A,D的根節點的C,加入要把C連到A,C與A的關系就有

A ← C      

↑      ↑     

B ← D  

 其中D到B的關系是給出的0或1,代表D與B是同類或D被B吃,B與A,D與C的關系都確定,再要求C與A的關系,其實可以很直觀的看出,就是C到D 的關系D到B的關系然后B到A的關系這樣這個向量加法,所以A ← C就是C→D加D->B加B->A,D->C的關系逆過來就是C->D了。同樣,若已經知道AB是同一根節點要判斷是不是假話,也是可以利用向量加法。

 1 #include<stdio.h>
 2 struct Animal{
 3     int root,is;//0跟根節點同類 1被根節點吃 2吃根節點 
 4 }A[51108];
 5 int gui(int x);
 6 int bing(int z,int x,int y);
 7 int main()
 8 {
 9     int i,n,m;
10     scanf("%d%d",&n,&m);
11     for(i=1;i<=n;i++)
12     {
13         A[i].root=i;//根節點初始為自己 
14         A[i].is=0;//自己是自己的同類 
15     }
16     int x,y,z,ans=0;
17     while(m--)
18     {
19         scanf("%d%d%d",&z,&x,&y);
20         if(x>n||y>n)
21             ans++;
22         else if(z==2&&x==y)
23             ans++;
24         else
25             ans+=bing(z,x,y); 
26     }
27     printf("%d\n",ans);
28 }
29 int gui(int x)
30 {
31     if(A[x].root==x)
32         return x;
33     int y=A[x].root,z=gui(A[x].root);//注意要先調整上一節點與根節點的關系再來調整
34     A[x].is=(A[x].is+A[y].is)%3;//處理他們的關系 
35     return A[x].root=z;
36 }
37 int bing(int z,int x,int y)
38 {
39     int bx=gui(x),by=gui(y);
40     if(bx==by)//X和Y有公共根節點,代表之前有真話把他們聯系在一起,此時方能判斷真假 
41     {
42         if((A[y].is+3-A[x].is)%3!=z-1)//與公共根節點的關系判斷話的真假 
43             return 1;
44     }//z-1就分別代表0 1 就xy同類還有y被x吃 
45     else
46     {
47         A[by].root=bx;
48         A[by].is=(A[x].is+3-A[y].is+z-1)%3;//向量加法 
49     }
50     return 0;
51 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM