食物链@POJ 1182

动物王国中有三类动物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

题目分析:一共有三种关系,0,1,2。具体说就是,r[i] = 0 表示 f[i] 和 i 是同类, r[i] = 1 表示 f[i] 吃 i ,r[i] = 2 表示 f[i] 被 i 吃。

然后就慢慢来吧,关于细节也是扒的别人题解。

还有不要用文件终止符等待题目输入结束,这个题只有一组测试数据,错了还不给我TLE,直接给个WA,我以为是什么细节问题,结果改了10多遍,真是尼玛。。。

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cstdio>
#include <stack>
#include <set>
#define MAXN 50004
using namespace std;

int f[MAXN],r[MAXN];
int ans;


int getf(int a){
    if(a == f[a]) return a;
    int t = getf(f[a]);
    r[a] = (r[f[a]] + r[a]) % 3;
    f[a] = t;
    return t;
}

void Union(int d,int a,int b){
    int fa = getf(a);
    int fb = getf(b);
    if(fa == fb){
        if((r[a]-r[b]+d+3)%3 != 0) ++ans;
        return;
    }
    f[fb] = fa;
    r[fb] = (r[a]+d-r[b]+3)%3;
}

int main(){
    int n,k;
    scanf("%d%d",&n,&k); //不要用文件终止符等待输入结束,直接这样就好了
    for(int i=1;i<=n;++i){
        f[i] = i;
        r[i] = 0;
    }
    ans = 0;
    int d,a,b;
    for(int i=0;i<k;++i){
        scanf("%d%d%d",&d,&a,&b);
        if(a > n || b > n || (d == 2 && a == b)){
            ++ans;
            continue;
        }
        Union(d-1,a,b); //就题而论,注意d-1这个细节问题,WA了几遍
    }
    cout << ans << endl;
    return 0;
}
扫描二维码关注公众号,回复: 2598233 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_39021458/article/details/81299636