poj 1182食物鏈 種類並查集

2021-06-29 16:50:55 字數 3768 閱讀 9712

食物鏈

time limit:1000ms

memory limit:10000k

total submissions:49310

accepted:14382

description

動物王國中有三類動物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),輸出假話的總數。 

input

第一行是兩個整數n和k,以乙個空格分隔。 

以下k行每行是三個正整數 d,x,y,兩數之間用乙個空格隔開,其中d表示說法的種類。 

若d=1,則表示x和y是同類。 

若d=2,則表示x吃y。

output

只有乙個整數,表示假話的數目。

sample input

100 7

1 101 1

2 1 2

2 2 3

2 3 3

1 1 3

2 3 1

1 5 5

sample output

3
分析:之前做過很多基礎並查集,然後帶權並查集,再就是種類並查集,某君說還要有異或並查集,馬甲。
在練帶權並查集時就雲裡霧裡,當時馬馬虎虎的就過了,這回我真心想重新撿起來,清清楚楚的研究透了,
因為以前就是浪費學了白學,過完年就忘的一清二楚了,之前做過很多有意思的帶權並查集,由於,急功
近利沒有真正的搞明白,搞熟練,現在都忘了。搞學習就是這樣,特別是acm包括計算機其他的,必須腳
踏實地,不然就是欺騙自己,做欺騙自己的事毫無意義,最終一無所獲。希望這些話對諸位有幫助。
好吧,就這到題吧:
這是乙個典型的種類並查集,說是種類並查集,然正如某君所說「不要說種類並查集和帶權並查集不一樣」。
首先定義:b是a的父節點即b=fa[a],若a與b同類則level[a]=0,若a吃b則level[a]=2,若a被b吃則
level[a]=2;
那麼在判斷是如果(level[b]-level[a]+3)%3!=d-1則為假話。
如果 fx=find(a),fy=find(b),a,b不屬於同一集合則fa[fy]=fx,level[fy]=(level[x]-level[y]+(d-1)+3)%3;
所以種類並查集核心就是匯出這些關係。在此之前我畫和很多顆樹,用了不同的關係式做出了這道題,於是
總結出了一句話就是:種類並查集與向量有關,它的匯出式就是向量的計算式。
好,那我們就來演示一下為什麼匯出了上述公式。
~首先已自定義了:b是a的父節點即b=fa[a],若a與b同類則level[a]=0,若a吃b則level[a]=2,若a被b吃則level[a]=2;
為了方便設type=d-1;
一、路徑壓縮
假設有乙個集合a-b-c-d;a是集合頂點(root),則向量ba=level[b],cb=level[c],dc=level[d];
(有子節點指向父節點);
則在壓縮路徑時需要更新所有的值(fa,level)。各位想壓縮後的關係是:a-b,a-c,a-d,即直接指向集合
頂點,fa[b]=a,fa[c]=a,fa[d]=a,這時level的計算是根據向量的計算來的,向量按照壓縮路徑的過程:
ba=ba <=> level[b]=level[b],
ca=ba+cb <=> level[c]=level[b]+level[c],
da=ba+cb+dc <=> level[d]=level[b]+level[c]+level[d];
因為壓縮是在find函式回溯是壓縮的,所以level[b]在level[c]之前更新,所以同理上式實際為
level[b]=level[b];
level[c]=level[b]+level[c];
level[d]=level[c]+level[d];
其實就是 level[x]=level[x]+level[fa[x]];
為了防止溢位該式改為:level[x]=(level[x]+level[fa[x]]+3)%3;
二、合併集合
假設type b d,開始b,d屬於不同集合,b屬於a-b,d屬於c-d,因此要合併這兩個集合;
type 為b d之間的關係數(題目中type=d-1)用向量表示db=type

一、知向量ba=level[b],向量dc=level[d],先要把c-d並成a-b的子樹;

則fa[c]=a和並完成,於此同時還要更新level[c]的值;
由於a成了c的子節點所以level[c]=ca=ba+db-dc=type+level[x]-level[y];
其實就是:level[fx]=level[x]-level[y]+type;
為防止溢位上式改為 level[fx]=(level[x]-level[y]+type+3)%3;
三、驗證
假設x y在同一集合中驗證type x y是否正確(type=d-1);
假設type x y正確即yx=type=ry-rx=level[y]-level[x];(r為此集合頂點);
為防止溢位上式改為type=(level[y]-level[x]+3)%3;
若不想等則為假話;
至此這道題的核心講完了。各位「~首先已自定義「這地地方可以自己定義,不一定這樣設,但我覺得0,1,2
這三個數比較簡單,也可以a吃b時level[a]=1啊(b=fa[a]),但是無論怎樣萬變不離宗、向量的特性是不變
的。
這是我對這道題和種類並查集的理解,下面獻上**:
#include#include#include#includeusing namespace std;

const int maxh=50000+10;

int fa[maxh],level[maxh],n,m;

void init(int num)

}int find(int x)

return fa[x];

}bool union(int x,int y,int type)

else

}int main()

if(type==2&&x==y)

if(!union(x,y,type-1))

sum++;

}printf("%d\n",sum);

return 0;

}

POJ 1182 食物鏈 (種類並查集)

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

POJ 1182 食物鏈(種類並查集)

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

POJ1182 食物鏈(種類並查集)

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