AcWing 240. 食物链

https://www.acwing.com/problem/content/242/

在这里插入图片描述

在这里插入图片描述

这道题看起来相当有难度,这道题不仅仅是一个并查集。更类似于一个带权并查集。
我们在这里引用了p[N],d[N].d是我们的权,指的是这个点到根节点的距离。然后根据y总讲的,距离根节点的距离模3的一些特殊性质(因为y总把它放在了一个树上),
1.模3余1时x吃y
2.模3余2时y吃x
3.模3余0时x,y同类。
在这里插入图片描述
在这里可以清楚的看到,模3余0的点离根节点最远的,是可以吃那个上一个点的,根节点也可以吃这个点,所以这两个点是一类。然后我们很明显我们要创建这个根节点为某一个值的树,我们用并查集实现这个功能,至于一些细节在代码中说清。

#include<iostream>
using namespace std;
const int N=1e5+10;
int p[N],d[N];
int find(int x)
{
    if(p[x]!=x)
    {
        int u=find(p[x]);
        d[x]+=d[p[x]];//原来的d[x]是x到p[x]的距离,加上父节点到根节点的距离,就是x到根节点的距离
        //为什么原来的d[x]是x到p[x]的距离,看下面标注的**
        p[x]=u;
    }
    return p[x];
}
int main(void)
{
    int n,m,res=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++) p[i]=i;
    for(int i=1;i<=m;i++)
    {
        int t,x,y;
        cin>>t>>x>>y;
        int px=find(x),py=find(y);
        if(x>n||y>n) res++;
        else if(t==1)
        {
            if(px==py&&(d[x]-d[y])%3) res++;
            else if(px!=py)
            {
                p[px]=py;
                d[px]=d[y]-d[x];//**这两处的标注都表明了这得到的是两个原来的父节点距离的差
                //这个意思是,y为根节点,x的祖宗到这个根节点的距离等于y到根节点的距离-x到祖宗的距离
                //这样一定能保证(d[x]-d[y])%3==0
                //因为(d[x](d[x]+d[px])-d[y])%3==0
            }
        }
        else if(t==2)
        {
            if(px==py&&(d[x]-d[y]-1)%3) res++;
            else if(px!=py)
            {
                p[px]=py;
                d[px]=d[y]-d[x]+1;//**
                //同理,这样一定能保证(d[x]-d[y])%3==1
                //因为(d[x](d[x]+d[px])-d[y])%3==1
            }
        }
    }
    cout<<res;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值