NOI2001T1 食物鏈 並查集

2021-07-16 13:25:46 字數 974 閱讀 2857

測試位址

題目大意:乙個地方的動物分a,b,c三類,a吃b,b吃c,c吃a,兩種動物之間要麼是同類,要麼就有吃與被吃的關係。按順序給定k句話,描述的是某兩種動物是同類或某種動物吃某種動物。求這些話中假話的數量(假話的定義在原題中有)。

做法:用f[i]表示i號動物所屬集合的代表動物,r[i]表示i號動物與它所屬集合代表動物之間的關係,為0時代表它們是同類,為1時代表i號動物吃它所屬集合的代表動物,為2時反之。由於動物之間的關係剛開始是不確定的,因此我們用並查集來記錄哪些動物之間的關係是可以確定的。每讀入乙個關係,如果關係涉及的兩種動物不屬於同乙個集合,則表示它們之間的關係仍不能確定,則認定這句話為真話,合併兩個集合。如果它們屬於同乙個集合,則表示它們之間的關係已經可以確定,則先求出它們之間的關係,再將它與描述中的關係比較,判斷是否為假話。關鍵就在於怎麼維護這個關係。這裡主要是合併和求某兩種動物之間關係的問題:合併時,如有兩種動物x,y,關係為d,因為x與f[x]關係為r[x],y與f[y]關係為r[y],得出f[x]和f[y]之間關係為(r[y]+d-r[x]+3) mod 3,括號裡加上3是為了防止減的結果為負數,然後再像普通並查集一樣合併即可。求兩種動物x,y之間關係,可以用上面的推論方法得出它們之間的關係為(r[x]-r[y]+3) mod 3。路徑壓縮中維護r的方法與上面的推論方法類似,不再贅述。至此,我們已經可以解決這個問題了。

以下是本人**:

#include #include #include #include using namespace std;

long n,k,ans=0,f[50010]=,r[50010]=;

long find(long x)

void merge(long x,long y,long len)

int main()

else merge(x,y,d-1);

} }

printf("%ld",ans);

return 0;

}

NOI2001T1 食物鏈 並查集

測試位址 題目大意 乙個地方的動物分a,b,c三類,a b吃c,c吃a,兩種動物之間要麼是同類,要麼就有吃與被吃的關係。按順序給定k句話,描述的是某兩種動物是同類或某種動物吃某種動物。求這些話中假話的數量 假話的定義在原題中有 做法 用f i 表示i號動物所屬集合的代表動物,r i 表示i號動物與它...

NOI2001 食物鏈 並查集

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

並查集 NOI2001 Day1 T3 食物鏈

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