1. 程式人生 > >有點意思的並查集

有點意思的並查集

set 歸並 但是 scanf http 他在 ring href 怎麽

K - How Many Answers Are Wrong HDU - 3038

題目大意:兩個人玩遊戲,一個人說一個區間內的數的和,然後判斷她說的有多少句和之前說過的沖突的。

一開始想的用一個數就代表他到根節點裏的數和,但是在路徑壓縮時明顯不對,因為已知[1,8],[8,10]並不能推出[1,10],但如果是(1,8],(8,10]就可以推出(1,10]。所以關鍵在於一個左開右閉的區間。

 1 #include<stdio.h>
 2 struct Extent{
 3     int gen,sum;//sum為區間(gen,x]內的和 
 4 }E[201108];
 5 int gui(int
x); 6 int bing(int x,int y,int z); 7 int main() 8 { 9 int n,m,i; 10 while(scanf("%d%d",&n,&m)!=EOF) 11 { 12 for(i=0;i<=n;i++) 13 { 14 E[i].gen=i; 15 E[i].sum=0;//一開始為空集即0 16 } 17 int x,y,z,ans=0; 18 while(m--) 19 {
20 scanf("%d%d%d",&x,&y,&z); 21 ans+=bing(x-1,y,z);//每次給的是[x,y]的值,所以歸並時是將x-1和y歸並 22 } 23 printf("%d\n",ans); 24 } 25 return 0; 26 } 27 int gui(int x) 28 { 29 if(E[x].gen==x) 30 return x; 31 int y=E[x].gen,z=gui(E[x].gen);//先回溯更新父節點和根節點的權
32 E[x].sum=E[y].sum+E[x].sum;//(a,b]和為sum1 (b,c]和為sum2 則(a,c]為sum1+sum2 33 return E[x].gen=z; 34 } 35 int bing(int x,int y,int z) 36 { 37 int bx=gui(x); 38 int by=gui(y); 39 if(bx==by) 40 { 41 if(E[y].sum-E[x].sum!=z) 42 return 1; 43 } 44 else 45 { 46 E[by].gen=bx; 47 E[by].sum=E[x].sum-E[y].sum+z;//向量加法 48 } 49 return 0; 50 }

E - Peculiar apple-tree CodeForces - 931D

題目大意;有一顆蘋果樹,有很多花(??我英語不好),然後第一朵在樹跟,其他在樹枝,每次每朵花會一個結果,然後同時往下掉p的花中,掉到同一朵花的時,偶數個的蘋果會全部碰碎,奇數個的只剩一個。問一個人在第一朵花能撿到的蘋果數量。

畫圖來理解就是看他們最後能不能掉到第一朵花,而怎麽處理同時掉落呢,距離。用它們到第一距離就可以代表時間了。註意距離不是高度,比如高度3的話蘋果掉到1,高度7的話的蘋果掉到3,那高度3 的話與第一朵花的距離是1,高度7與第一朵花的距離是2。這樣,然後就是一個並查集。然後看它們到第一朵花的距離,相同的就會碰到一起。

 1 #include<stdio.h>
 2 #include<string.h>
 3 struct Apple{
 4     int gen,dis;//gen是這個蘋果最後會掉到哪朵花 dis是這朵花到gen的距離 
 5 }A[101108];
 6 int book[101108];
 7 inline int gui(int x){
 8     if(A[x].gen==x)
 9         return x;
10     return A[x].gen=gui(A[x].gen);
11 }
12 int main()
13 {
14     int n,i,p;
15     scanf("%d",&n);
16     for(i=1;i<=n;i++)
17     {
18         A[i].gen=i;//一開始蘋果結在這個花這裏 
19         A[i].dis=0;//距離沒得說就是0 
20     } 
21     for(i=2;i<=n;i++)
22     {
23         scanf("%d",&p);
24         A[gui(i)].gen=gui(p);//並查集,讓它的gen為最後掉到的地方 
25         A[i].dis=A[p].dis+1;//而它到gen的距離就是它下一個掉落的地方的距離+1 
26     } 
27     memset(book,0,sizeof(book));
28     for(i=1;i<=n;i++)//從第一個蘋果開始 
29         if(gui(i)==1)//如果能掉到第一朵花 
30             book[A[i].dis]++;
31     //因為蘋果都是同時掉落,所有用距離來代表時間,如果到達gen的距離相同說明他們會碰到一起
32     //book就統計最終能到第一朵花的花的距離,看一下每個距離相同的有多少個
33     int ans=0;
34     for(i=0;i<n;i++)
35         ans+=book[i]%2;//最後對2取模,同時間如果有偶數個蘋果碰到一起就全部銷毀,奇數個只剩一個 
36     printf("%d\n",ans);
37     return 0;
38 }

有點意思的並查集