Luogu P2024 [NOI2001]食物链

并查集

首先先要读懂题目,a是b的食物的话,b的天敌是a,b的食物是a的天敌

比如,人吃鸡,鸡吃草,那么草吃人。。。。。

所以建3个并查集,+n时表示这是其食物,+2*n时表示这是其天敌

所以当x,y是同类当且仅当x的食物不是y,且x的天敌不是y

当x吃y当且仅当x和y不是同类,y的食物不是x

然后并查集维护即可

#include <bits/stdc++.h>
using namespace std;
const int MAXN=51000;
int n,k,fa[MAXN*4],ans;//1 same 2 food 3 enemy
inline int find(int x)
{
    if (fa[x]==x)
      return fa[x];
    fa[x]=find(fa[x]);
    return fa[x];
}
void unite(int x,int y)
{
    int fx,fy;
    fx=find(x);
    fy=find(y);
    fa[fx]=fy;
}
int main()
{
    scanf("%d%d",&n,&k);
    for (int i=1;i<=3*n+10;i++)
      fa[i]=i;
    for (int i=1;i<=k;i++)
    {
        int d,x,y;
        scanf("%d%d%d",&d,&x,&y);
        if (x>n ||y>n)
        {
            ans++;
            continue;
        }
        if (d==1)
        {
            if (find(x+n)==find(y) || find(x+n*2)==find(y))
            {
                ans++;
                continue;
            }
            unite(x,y);
            unite(x+n,y+n);
            unite(x+2*n,y+2*n);//三个并查集的同类都要连起来
        }
        else
        {
            if (x==y || find(x)==find(y) || find(x+2*n)==find(y))
            {
                ans++;
                continue;
            }
            unite(x+n,y);
            unite(x+2*n,y+n);
            unite(x,y+2*n);//三个并查集维护
        }
    }
    printf("%d\n",ans);
}

 

上一篇:【POJ - 1182】食物链(并查集)


下一篇:食物链