poj 食物鏈 資料結構 並查集

2021-07-09 02:45:19 字數 2917 閱讀 2254

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
source

noi 01

解法一 用帶權值的並查集

本題就是需要我們判斷給定的兩點是否滿足某種關係。同一顆樹裡面的任意兩節點間的關係我們是想知道的。

1。。根據向量如果已知a與b的關係(共只有三種關係),b與c的關係,那定會推出a與c的關係,可以在紙上畫畫,更清楚。據此,就能求得每個節點到其根節點的關係。

2。。 對於現在不在同一顆樹中元素,合併前需知道兩個子樹的根節點的關係。這在後面的推倒

上面兩個問題是解本題的核心!!!

之前並查集是處理的一類的元素操作,而該題元素之間有關係(同類,吃,被吃),因此對於每個元素除了需要儲存每個元素的父親節點,還需儲存於父親節點的關係。

之前的樹裡面代表任意兩個數在乙個集合,而此問題代表任意兩個數的關係的以確認。

在進行樹與樹間合併時,是合併已經確定關係的元素,如現有根節點a的子樹 、根節點b的子樹如知道節點a 與節點b的關係就可合併。根據我們儲存的資訊我們可以推出任意節點與其根節點的關係,具體細節見**注釋。

補充:我看別人都說向量解答,剛開始有點懵,然後發現有點像相對位置,可以相加(特殊的規則),因此本問題可以擴充套件多個不同種類的動物。

#include#include#include#include#include#includeusing namespace std;

int fa[50010];

int r[50010];

int ct;

void init(int n)

}int find(int x)

return fa[x];

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

return 0;

}fa[rx] = ry;

r[rx] = (d-1 + r[y] - r[x] +3)%3; // ( ((d-1) +r[y]) + (3-r[x]) )%3

//把x所在的子樹連線到y的根節點上 (只需改x的根節點rx與y的根節點ry的關係)

// 公式的推倒,是難點!!! 首先我們已知x與y的關係(就是d的值),x與x的根節點的關係(即為r)

// 首先可以通過r【i】,r【fa】的值知道i與fa【fa【i】】的關係 這裡我們可以匯出x與ry的關係(1)

// 然後還需推倒一下:通過r【i】的值,匯出父親對孩子的關係, 這裡我們可以匯出rx與x的關係(2)

//最後 在利用一下 1 的性質知道 rx與ry的關係 這裡我們可以匯出rx與ry的關係

return 0;

}int main()

tmp = union(d,x,y);

//if(tmp)

ct += tmp;

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

return 0;

}

法2

巧妙地解法,超出常規的思維。

把本題變種成一般的並查集。 同樣

本題就是需要我們判斷給定的兩點是否滿足某種關係。同一顆樹裡面的任意兩節點間的關係我們是想知道的。

該開始第一次看本題在《挑戰程式設計》中沒懂。。

此次了解了。

#include#include#include#include#include#includeusing namespace std;

int fa[3*50010];

int r[3*50010];

int find(int x)

return fa[x];

}int same(int x,int y)

void merge(int x,int y)

else

fa[y] = x;

}} int main()

for(i=0;in || y>n)

if(d==1)

merge(x,y);

merge(x+n,y+n);

merge(x+2*n,y+2*n);

} else

merge(x , y+n);

merge(x+n , y+2*n);

merge(x+2*n , y);} }

printf("%d\n",count);

return 0;

}

poj 食物鏈 (種類並查集)

種類並查集的經典題 飄過的小牛 關係域更新 當然,這道題理解到這裡思路已經基本明確了,剩下的就是如何實現,在實現過程中,我們發現,更新關係域是乙個很頭疼的操作,網上各種分析都有,但是都是直接給出個公式,至於怎麼推出來的都是一筆帶過,讓我著實頭疼了很久,經過不斷的看discuss,終於明白了更新操作是...

POJ 食物鏈 種類並查集

time limit 1000ms memory limit 10000k 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係...

並查集 食物鏈

noi2001,水題,但是我調了很久。食物鏈time limit 1000ms memory limit 10000k total submissions 27766 accepted 8066 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃...