首页
登录 | 注册

poj食物链,经典带权并查集

题目描述

动物王国中有三类动物 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 句话有的是真

的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

• 当前的话与前面的某些真的话冲突,就是假话

• 当前的话中 X 或 Y 比 N 大,就是假话

• 当前的话表示 X 吃 X,就是假话

你的任务是根据给定的 N 和 K 句话,输出假话的总数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
 const int maxn=1e5+10;
int fa[maxn],rnk[maxn];//rnk点与根的关系
int n,k;
void init(int x){
    for(int a=0;a<=x;a++){
        fa[a]=a;
        rnk[a]=0;
    }
}
int findfa(int x){
   if(fa[x]==x)
       return x;
   else{
       int mid=fa[x];
       fa[x]=findfa(fa[x]);//压缩
       rnk[x]=(rnk[x]+rnk[mid])%3;//节点与根的关系     rnk[mid]是mid与根结点的关系
       return fa[x];//第二个rnk[x]是当前的点到压缩前的根的关系,rnk【mid】是之前的根到当前的根的关系,两者相加即为当前的点到当前的根的关系
   }
}
void merge(int r,int x,int y){
    int fx=findfa(x);
    int fy=findfa(y);
    if(fx!=fy){
        fa[fx]=fy;
        rnk[fx]=(rnk[y]-rnk[x]+r+3)%3;
    }
}
bool check(int a,int b,int c){
    if (b>n||c>n||b<1||c<1) {
        return false;
    }
    if(a==1&&b==c)
        return false;
    int fb=findfa(b);
    int fc=findfa(c);
    if(fb==fc)
        return  a==(rnk[b]-rnk[c]%3+3)%3;
    else
        return true;
}
int main()
{
    int ans = 0;
    scanf("%d %d",&n,&k);
    init(n);
    for (int a=0; a<k; a++) {
        int o,p,q;
        cin>>o>>p>>q;
        o--;
        if(check(o,p,q))
            merge(o,p,q);
        else
            ans++;
    }
    printf("%d\n",ans);
    return 0;
}



2020 jeepxie.net webmaster#jeepxie.net
10 q. 0.008 s.
京ICP备10005923号