time limit: 1000ms memory limit: 10000k
total submissions: 77869 accepted: 23180
動物王國中有三類動物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),輸出假話的總數。
第一行是兩個整數n和k,以乙個空格分隔。
以下k行每行是三個正整數 d,x,y,兩數之間用乙個空格隔開,其中d表示說法的種類。
若d=1,則表示x和y是同類。
若d=2,則表示x吃y。
只有乙個整數,表示假話的數目。
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
noi 01
分析:
大概是第一次做帶權並查集的題,感覺這道題好巧,各種公式什麼的理解了好久。
並查集可以查詢兩個元素是否在同乙個元素裡,並且很快地合併兩個集合。而這道題在並查集簡單地合併與查詢元素關係的基礎上,還加入了元素的權值。(因為這次的關係除了是否同屬於一種元素外,還有吃與被吃的關係。)
我們用rk來儲存每個元素的關係。其中定義rk的含義如下:
rk==0,表示父子屬於同一種元素
rk==1,這個節點被父節點吃
rk==2,父節點被這個節電吃
這樣定義之後會有很多方便之處。
直接解釋幾個公式吧:
rk[g]=(rk[s]+rk[f])%3
這個在路徑壓縮的時候會用到,即已知乙個節點與父節點的關係和父節點和爺爺節點的關係,求這個節點與爺爺節點的關係。
【這個可以自己手動推一下,對每種情況都是滿足的
rk[x]+3-rk[y]
這個是在判斷x和y是否是同一類的時候用到的。
如果x對y的關係是rk[x],那麼y對x的關係就是(3-rk[x])%3 【這個也可以簡單模擬一下,不難得出
那麼x接rt,關係為rk[x],y也接rt ,關係為rk[y] 我們就可以先得出rt與y的關係,此時x與y就是爺孫關係(感覺這句話好奇怪),然後就可以求出x與y的關係,再與給出的關係判斷一下是否一致就可。
注意:如果給出的x和y的關係是0,那麼我們只需要判斷rk[x]和rk[y]是否一致就可。(不過用這個式子也可以)
rk[fx]=(tmp-1+3-rk[x]+rk[y])%3
tmp為給出的關係。
此時為給出的x和y之前沒有在乙個集合中(肯定不是謊話),我們需要把x的根fx接在y的根fy上。
具體實現相當於把fx接在x上,x接在y上,y在fy上。
(但要路徑壓縮)
首先先利用tmp-1得到y與x的關係
再利用3-rk[x] 得到fx對於x的關係
此時就得到了fx與y的關係:
rk[fx]=(tmp-1+3-rk[x])%3;
最後再利用第乙個式子得到fx與fy的關係,即給出的式子
馬丹理解這些公式理解了好久,但理解完感覺成就感up2333
【好久沒寫過這麼長的部落格了
#include
#include
#include
using namespace std;
inline int
read()
while(ch>='0'&&ch<='9')
return
x*f;
}const int n = 100010;
int ans=0;
int n,k;
int fa[n],rk[n];
int find(int
x)int query(int tmp,int
x,int
y) else
}fa[fx]=fy;
rk[fx]=(tmp-1+3-rk[x]+rk[y])%3;
return0;}
int main()
if(x==y&&tmp!=1)
ans+=query(tmp,x,y);
}printf("%d\n",ans);
return
0;}
poj 1182 食物鏈 帶權並查集
這個題需要將動物分成3種,每次以y 0為物件,吃他的x為1,需要注意的是下一次碰到x cha函式遞迴更新與x有關的物件 include include include includeusing namespace std define n 50005 int father n num n int c...
poj1182食物鏈 帶權並查集
基本思路 帶權並查集 簡單的理解就是將有關係的點合併到乙個集合,記錄每個點到集合根節點的權重 include include include define max 50010 using namespace std int par max 記錄集合根節點 int offset max 記錄每個節點到...
poj 1182 食物鏈 帶權並查集
食物鏈 time limit 1000ms memory limit 10000k total submissions 50713 accepted 14818 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n...