洛谷2024食物链——带权并查集

题目:https://www.luogu.org/problemnew/show/2024

思路很重要。明确当“1”时只需a与b没有吃与被吃关系即可;当“2”时只需a与b不是同类也不是相反的吃的关系即可。

      不需要很麻烦地想很多判断条件!

      别忘了每次添加足够的新关系。

自己注意点:1.明确每个值仅有fa[ i ],没有“ i 本身”。故为了一开始的区分,给每个fa[ ]赋值成本身是很重要的;这就像给每个点打上了自己独特的标记。

      自己曾试图用二维数组来表示补集,但问题在于别的点连接该点时,因为表示该点的脚标一样,故无法区分连的是该点的哪个集合。

      ——即使是同一个点,也该在 脚标 / 初值 上有所区分呢!

      2.无需a+50000,只要a+n即可;

      3.区分清楚变量自己和变量的值。如果用u来代表find(a),到时候改值不是改变u的值而是改变fa[ a ]的值!

#include<iostream>
#include<cstdio>
using namespace std;
int n,k,fa[150005],a,b,c,fs;
int find(int a)
{
    if(fa[a]==a)return a;
    return fa[a]=find(fa[a]);
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=3*n;i++)
        fa[i]=i;
    for(int t=1;t<=k;t++)
    {
        scanf("%d%d%d",&c,&a,&b);
        if(a>n||b>n)
        {
            fs++;
            continue;
        }
        if(c==1)
        {
            int u=find(a+n);
            int v=find(b+n);
            int r=find(a+2*n);
            int e=find(b+2*n);
            int o=find(a);
            if(o==v||o==e)
            {
                fs++;
                continue;
            }
            fa[o]=fa[b];
            fa[u]=fa[b+n];
            fa[r]=fa[b+2*n];
        }
        if(c==2)
        {
            int u=find(a);
            int v=find(b);
            int x=find(a+n);
            int y=find(a+2*n);
            int r=find(b+n);
            if(u==v)
            {
                fs++;
                continue;
            }
            if(u==r)
            {
                fs++;
                continue;
            }
            fa[x]=fa[b];
            fa[u]=fa[b+2*n];
            fa[y]=fa[b+n];
        }
    }
    printf("%d",fs);
    return 0;
}

 

posted on 2018-01-13 00:14  Narh  阅读(155)  评论(0编辑  收藏  举报

导航