打包商品 题解(并查集)

题目链接

题目思路

其实看到合并就要想到并查集,但是自己还是不知道怎么写,其实也相当于是一个裸题,把sm数组和bi数组初始化为自己的值。

然后再更新是一样的操作,还有更新最大值和最小值的情况只要更新祖宗节点就可以,不要全部跟新,要不然就出锅(我就wawawa了

还有题目有一个找最小编号的操作,其实完全没有必要用一个数组,直接联合的时候让自己父亲节点的值小就好。

还有合并的时候一定注意是祖宗节点合并,wa过很多次了

代码

#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=1e5+5;
int n,m,k,a[maxn],fa[maxn],bi[maxn],sm[maxn];
//bi数组存最大值,sm数组存最小值,num数组存最小编号
int finddad(int x)//找父亲,路径压缩
{
    if(x==fa[x])
        return x;
    return fa[x]=finddad(fa[x]);
}
int findmax(int x)//找最大值
{
    return bi[finddad(x)];
}
int findmin(int x)//找最小值
{
    return sm[finddad(x)];
}
void unite(int x,int y)//合并
{
    if(x<y)//让祖宗的编号最小
    {
        swap(x,y);
    }
    fa[x]=y;
    bi[x]=bi[y]=max(bi[x],bi[y]);
    sm[x]=sm[y]=min(sm[x],sm[y]);
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        fa[i]=i;//初始化
        bi[i]=a[i],sm[i]=a[i];
    }
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        int x=max(findmax(u),findmax(v));
        int y=min(findmin(u),findmin(v));
        u=finddad(u);//合并祖宗
        v=finddad(v);
        if(x-y<=k)//满足可以合并的条件
        {
            unite(u,v);
        }
    }
    for(int i=1;i<=n;i++)
    {
        int x=finddad(i);
        int y=bi[x]-sm[x];
        printf("%d %d\n",x,y);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值