並查集 poj1182 noi2001食物鏈eat

2021-07-01 19:39:40 字數 4581 閱讀 4344

題意

有三類動物a,b,c,題中給出兩種關係:

1 x y :x y 同類

2 x y :x吃y

對於假話的定義:

1.當前的話與前面的某些真的話衝突,就是假話;

2.當前的話中x或y比n大,就是假話;

3.當前的話表示x吃x,就是假話。

現在給出n句這樣的關係,求假話個數。

分析這是第二次寫這道題了,第一次是去年剛學並查集的時候。當初囫圇吞棗a了,現在拿出來發現自己根本就沒明白。

感覺,經典的題還是要時常拿出來做一做。

剛才某人吐槽:這題比就我小4歲。呵呵....

廢話少說,說正題。

看題解寫的,這個人的分析很詳細哦~!膜拜!

感覺他說的太詳細了,所以鄙人就摘抄並整理修改一下這位大神的,自己也沒什麼可寫的了...謝謝大神

part i - 權值(relation)的確定。

我們根據題意,森林中有3種動物。a吃b,b吃c,c吃a。

我們還要使用並查集,那麼,我們就以動物之間的關係來作為並查集每個節點的權值。

注意,我們不知道所給的動物(題目說了,輸入只給編號)所屬的種類。

所以,我們可以用動物之間「相對」的關係來確定乙個並查集。

0 - 這個節點與它的父節點是同類

1 - 這個節點被它的父節點吃

2 - 這個節點吃它的父節點。

注意,這個0,1,2所代表的意義不是隨便制定的,我們看題目中的要求。

說話的時候,第乙個數字(下文中,設為d)指定了後面兩種動物的關係:

1 - x與y同類

2 - x吃y

我們注意到,當 d = 1的時候,( d - 1 ) = 0,也就是我們制定的意義

當 d = 2的時候,( d - 1 ) = 1,代表y被x吃,也是我們指定的意義。

所以,這個0,1,2不是隨便選的

part ii - 路徑壓縮,以及節點間關係確定

確定了權值之後,我們要確定有關的操作。

我們把所有的動物全初始化 relation[i]=0,f[i]=i

(1)路徑壓縮時的節點演算法

通過窮舉我們可以發現

f[now]=f[f[now]]

relation[now]=(relation[now]+relation[f[now]]) % 3

這個路徑壓縮演算法是正確的

關於這個路徑壓縮演算法,還有一點需要注意的地方,我們一會再談

注意,根據當前節點的relation和當前節點父節點的relation推出

當前節點與其父節點的父節點的relation這個公式十分重要!!

它推不出來下面都理解不了!!自己用窮舉法推一下:

好吧,為了方便伸手黨,我給出窮舉過程

i      j

爺爺  父親 兒子      兒子與爺爺

0      0      (i + j)%3 = 0

0      1      (i + j)%3 = 1

0      2      (i + j)%3 = 2

1      0      (i + j)%3 = 1

1      1      (i + j)%3 = 2

1      2      (i + j)%3 = 0

2      0      (i + j)%3 = 2

2      1      (i + j)%3 = 0

2      2      (i + j)%3 = 1

嗯,這樣可以看到,( 兒子relation + 父親relation ) % 3 = 兒子對爺爺的relation

所以有relation[now]=(relation[now]+relation[f[now]]) % 3

這就是路徑壓縮的節點演算法

(2) 集合間關係的確定

relation[find(y)]=(3-relation[y]+(d-1)+relation[x]) % 3;

這個公式,是分三部分,這麼推出來的:

( d - 1 ) :這是x和y之間的relation,x是y的父節點時,y的relation就是這個

3 - relation[y] = 根據y與根節點的關係,逆推根節點與y的關係

這部分也是窮舉法推出來的,我們舉例:

0(父子同類)( 3 - 0 ) % 3 = 0

1(父吃子) ( 3 - 1 ) % 3 = 2 //父吃子

2(子吃父) ( 3 - 2 ) % 3 = 1 //子吃父,一樣的哦親

所以有y的父結點與x的父結點關係relation[find(y)]=(3-relation[y]+(d-1)+relation[x]) % 3;

注意,這個當所有集合都是初始化狀態的時候也適用

part iii - 判斷

先處理特殊情況:      

1.當x>n或y>n時,為假話(在這裡竟然wa了一次...囧還是太不認真了)

2.當d=2而x=y時,為假話

其實所有的不同集合到最後都會被合併成乙個集合的。我們只要在乙個集合中找那些假話就可以了。

(1)首先,如何判斷

1 x y是不是假話。//此時 d = 1

if ( x 和 y 不在同一集合) union(x,y,xroot,yroot,d)   

else if x.relation != y.relation ->假話

(2)其次,如何判斷

2 x y是不是假話 //此時d = 2

if ( x 和 y 不在同一集合)union(x,y,xroot,yroot,d)

else (relation [y]+ 3 - relation[x] ) % 3 != 1 ->假話

這個公式是這麼來的:

3 - relation[x]得到了根節點關於x的relation,

relation [y]+ 3 - relation[x]得到了y關於x的relation

所以,只要y關於x的relation不是1,就是y不被x吃的話,這句話肯定是假話!

綜合(1) 和(2),無論d=1或2,只要滿足 ((relation[y]-relation[x]+3) mod 3)<>(d-1)

即為假話

accepted code

167

program poj1182;

8const

9 infile = '

poj1182.in';

10 outfile = '

poj1182.out';

11var

12 relation,f:array[0..50030

]of longint;

13n,k,d,x,y,ans,i,fx,fy:longint;

14function find(x:longint):longint;

15var

16fx:longint;

17begin

18 if f[x]=x then exit(x)

19else begin

20 fx:=find(f[x]);

21 relation[x]:=(relation[x]+relation[f[x]]) mod 3

;22 f[x]:=fx;

23exit(fx);

24end;

25end;

26procedure union(x,y,fx,fy,d:longint);

27begin

28 f[fy]:=fx;

29 relation[fy]:=(3-relation[y]+d-1+relation[x]) mod 3;30

end;

31begin

32assign(input,infile);reset(input);

33assign(output,outfile);rewrite(output);

34readln(n,k);

35 for i:=1

to n do begin

36 f[i]:=i;

37 relation[i]:=0;38

end;

39 for i:=1

to k do begin

40readln(d,x,y);

41 if (x>n) or (y>n) then begin

42inc(ans);

43continue;

44end;

45 if (d=2) and (x=y) then begin

46inc(ans);

47continue;

48end;

49 fx:=find(x);fy:=find(y);

50 if fx<>fy then union(x,y,fx,fy,d);

51else begin

52 if (((relation[y]-relation[x]+3) mod 3)<>(d-1

)) then inc(ans)

53end;

54end;

55writeln(ans);

56close(input);close(output)

57end.

58

poj 1182 帶權並查集

description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y是...

poj1182 帶權並查集

題意 中文題就不描述了 思路 帶權並查集模板題 加入乙個陣列 表示這個點和它父節點的關係 表示同類,表示父親吃它,表示它吃父親 每次需要更新和父親之間的關係 include includeconst int n 50005 int p n r n n,k void init int x int fi...

POJ 1182 帶權並查集

食物鏈 time limit 1000ms memory limit 10000k total submissions 89563 accepted 26905 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n...