食物鏈
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 7sample output1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
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編...