題目描述:
動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a**, 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 output3
思路分析:這道題一開始的想法是用帶權並查集,後來發現至少需要三組陣列,每次還要分很多情況,太麻煩了,於是看大佬的部落格,發現並查集居然還能這樣用!之前一直是想著假設一開始的是a類,然後後來者根據情況對應之。思維侷限。完全不需要確定誰具體是a還是bc呀,只需要知道他們之間的關係就行
大佬思路如下:
我們不關心小動物具體是abc,只關心他們之間的關係,所以每個動物都有abc類三種可能,三種可能表示的對應關係是一樣的,我們判斷關係的時候只需要假設都是a類即可。
開三倍空間,前50000表示a類,中間50000表示b類,後50000表示c類。跨類別同祖先表示捕食關係,同類別同祖先表示同類關係。如此一來,下標就能表示捕食關係,比如如果a中有1,b中有2,那麼就可以表示1吃2。單純下標表示捕食關係是不夠的,比如123456,既能表示1吃2也能表示2吃1。
所以再用並查集的父子關係來表示捕食關係,**食者祖先是捕食者。這樣的話123456就成了153153,a中的1和b中的2都返回1,所以a中的1和b中的2等價,僅表示1吃2
這道題的歸併是有邏輯先後的,不能壓縮路徑!
如果x,y同類關係的話,就將abc類裡x,y都合併。
例子:aaa
bbbc
cc12
3456
789初始狀態aa
abbb
ccc1
22n+245
278n+2
輸入 2吃3aa
abbb
ccc1
2n+1
2n+241
27n+1n+2
輸入 1吃2
此時,a1的祖先是1,b3的祖先是,2 -> 2n+1 -> 7,7在c類,而1在a類,所以3吃1
#include #include #include #include #include #include using namespace std;
int tree[150050];
int find(int x)
int same(int a,int b)
void unite(int a,int b)
}int main()
while(k--)
if(t==1)
else
}if(t==2)
else
}// printf("%d|%d|%d|%d|%d|%d|%d|%d|%d\n",tree[1],tree[2],tree[3],tree[n+1],tree[n+2],tree[n+3],tree[2*n+1],tree[2*n+2],tree[2*n+3]);
// printf("%d*\n",ans);
}printf("%d\n",ans);
}
解法二:
帶權並查集
本題目只需要知道相對關係,並不需要明確小動物具體是abc哪一類。而帶權並查集的權值可以表示與父節點的相對關係,所以可以用帶權並查集解這道題。
tree[y]=x,表示y和x有關係,同乙個根節點表示在同乙個已知關係裡,也就是說在同一條食物鏈中。value為0表示某節點與父節點同類關係,1表示吃父節點,2表示被父節點吃。我們只需要知道每個節點和父節點的關係,在路徑壓縮的時候層層向上修改即可
權值更新和判斷可以擬幾個例子歸納出來
#include #include #include #include #include #include using namespace std;
int n,k,d,x,y,ans;
int tree[50010];
int value[50010];
int find(int x)
return tree[x]=tmp;
}int main()
while(k--)
int rx=find(x);
int ry=find(y);
if(d==1)
else }}
if(d==2)
else }}
}printf("%d\n",ans);
return 0;
}
帶權並查集
Poj 1182 食物鏈 (兩種思路)
思路 對每個節點維護其到根節點的偏移量 偏移量代表種類關係 par x 表示x的根節點,rel x 表示x與根節點的偏移量。rel x 0表示x與根節點為同類,1表示根節點吃x,2代表x吃根節點。同類 不同類時,如何判斷關係是否矛盾以及如何合併兩頂點所在的集合。include include inc...
POJ 1182 食物鏈 Union Find題解
union find就是所謂的並查集。本題做的很無語,最後發現居然是輸入搞錯,一直wa。不能使用迴圈接受輸入,否則是wa的,氣死人,浪費那麼多時間就為了這個。難點 1 構建關係樹 2 構建公式 3 快速更新公式 要抽象思維出什麼對應什麼的關係和上面是逆關係,就是利用0,1,2構建出父子節點之間的關係...
POJ 1182 食物鏈 解題報告
食物鏈 time limit 1000ms memory limit 10000k total submissions 70529 accepted 20875 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n...