食物鏈
動物王國中有三類動物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
參考《挑戰程式設計》,裡面對這一道題的處理辦法是將a b c 三個種群的捕食關係分別放到乙個一維陣列裡面,然後進而將一維陣列三等分,然後分別處理,這和poj1703種類並查集的處理方法差不多
參考blog:
#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int n = 50010;
const int inf=0x3f3f3f3f;
int f[n*3];
int n,k,ans;
int findf(int v)
}void union(int x,int y)
bool same(int x,int y)
int main()
if(x>n||y>n||x<1||y<1)
if(d==1)
union(x,y);//如果x與y不是捕食關係話,那他們就是應該在同乙個種群中
union(x+n,y+n);//但是不知道他們是屬於哪乙個種群,因此我們將其分別分到
union(x+2*n,y+2*n);//三段種群中去
}else
union(x,y+n);
union(x+n,y+2*n);
union(x+2*n,y);}}
printf("%d\n",ans);
}
另外一種方法
在這個方法裡面我對最終下面的**有點困惑
void unite(int x,int y,int d)
參考了一下
對 r[fy] = (r[x]-r[y]+3+(d-1))%3; +3可以是認為去除負數的情況的,還有兩個不同的根節點他們之間要合併的關係是根據向量向量來規定得到的;
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...