POJ 1182 食物鏈/並查集

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


解題思路:根據題目知道兩種狀態,同類和捕食關係。我們需要判斷每條語句的正誤,同時也要維護正確信息,所以爲每隻動物i創建三個元素i-a,i-b,i-c,並用這3*n個元素開一個並查集。這個並查集要維護動物i所屬種類和這個並查集內元素所代表的統一性。

對於每一條信息,我們需要維護的:

1,第一種,兩隻動物(x,y)屬於同一種,合併x-a和y-a,x-b和y-b,x-c和y-c;

2,第二種,兩隻動物(x,y)x吃y,合併x-a和y-b,x-b和y-c,x-c和y-a。

當然維護之前,我們要先判斷一下信息的正誤(這次信息是否與之前的信息矛盾)和是否數據越界。

AC代碼:

<pre name="code" class="cpp">#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

int par[500050];
int rank[500050];

int find(int n)
{
    if(par[n] == n) return n;
    else return par[n] = find(par[n]);
}
void unite(int x,int y)
{
    x = find(x);
    y = find(y);
    if(x == y) return;
    par[y] = x;
}
bool same(int x, int y)
{
    return find(x) == find(y);
}//並查集格式,敲錯會wa
int main()
{
    int n, k;
    int t, x, y;
    scanf("%d%d",&n,&k);
    int ans = 0;
    for(int i = 0; i <= 3 * n; i++) par[i] = i;
    for(int i = 0; i < k;i++)
    {
        scanf("%d%d%d",&t,&x,&y);
        if(x>n||y>n||x < 1|| y < 1)//判斷數據是否超界
        {
            ans++;
            continue;
        }
        if(t == 1)//判斷種類
        {
            if(same(x,y+n)||same(x,y + 2*n)) ans++;//判斷x,y是否是異組
            else{
                unite(x,y);//同組合併
                unite(x + n,y + n);
                unite(x + 2*n, y + 2*n);
            }
        }
        else
        {
            if(same(x,y)||same(x,y + 2*n)) ans++;//判斷x,y是否是一組
            else
            {
                unite(x,y+n);//異組合並
                unite(x + n,y + 2*n);
                unite(x + 2*n,y);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章