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
3source
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吃...