codevs 1074 食物鏈(並查集)

題目描述 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 Description
第一行是兩個整數N和K,以一個空格分隔。   

以下K行每行是三個正整數D,X,Y,兩數之間用一個空格隔開,其中 D 表示說法的種類。   

若D=1,則表示X和Y是同類。   

若D=2,則表示X喫Y。

輸出描述 Output Description
只有一個整數,表示假話的數目。

樣例輸入 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

數據範圍及提示 Data Size & Hint
輸入文件

對7句話的分析 100 7

1 101 1  假話

2 1 2   真話

2 2 3   真話

2 3 3   假話

1 1 3   假話

2 3 1   真話

1 5 5   真話

思路:考慮到兩兩動物之間的關係並且需要在線統計答案,這題顯然可以用並查集來做。但動物之間還有喫與被喫的關係,普通的並查集是無法維護的,所以我們可以將並查集擴大三倍,分別維護同類、喫、被喫之間的關係。

注意:只存在三種類型的動物組成一個圈,不會出現a同時喫b和c的情況。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=5*10000*3+10;
int f[maxn]; 
int find(int w)//路徑壓縮
{
    if(w!=f[w])
    {
        f[w]=find(f[w]);
    }
    return f[w];
}
int main()
{

    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=3*n;i++)
    {
        f[i]=i;
    }
    int ans=0;
    for(int i=1;i<=k;i++)
    {
        int s,x,y;
        scanf("%d%d%d",&s,&x,&y);
        if(x>n||y>n)//x與y大於n爲假話
        {
            ans++;
            continue;
        }
        if(s==1)
        {   
            if(find(x)==find(y+n)||find(x)==find(y+2*n))//x喫y或x被y喫都不行
            {
                ans++;
                continue;
            }
            f[find(x)]=find(y);//x與y是同類
            f[find(x+n)]=find(y+n);//x喫的動物和y喫的動物是同類
            f[find(x+2*n)]=find(y+2*n);//喫x的動物和喫y的動物是同類
        }
        if(s==2)
        {
            if(find(x)==find(y)||find(x)==find(y+n))//x和y同類或y喫x都不行
            {
                ans++; 
                continue;
            }
            f[find(x+n)]=find(y);//x喫y
            f[find(y+n*2)]=find(x);//y被x喫
            f[find(x+n*2)]=find(y+n);//x被喫y的動物喫
        }
    }
    printf("%d",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章