首页 > 其他 > 详细

带权并查集

时间:2019-10-30 15:38:32      阅读:83      评论:0      收藏:0      [点我收藏+]

带权并查集 啦啦啦

   太厉害了  

 就是合并的时候加个权值,找祖父时加个权值。 对于闭区间的时候一定要变成开区间 a-1  ->B

   找祖父

int find(int a)
{
    if(a!=fa[a])
    {
        int t=fa[a];
        fa[a]=find(fa[a]);
        val[a]+=val[t]; // 跟新 这个节点到 祖父的 权值 
    }
    return fa[a];
}

  合并

    int l=find(a);
            int r=find(b);
            if(l!=r)
            {
                fa[l]=r;
                val[l]=-val[a]+c+val[b];   //跟新权值 
            }
            else
            {
                if(val[a]-val[b]!=c) ans++;// 解决问题 小的节点到 祖父的权值 大 
            }
        }

例题:

 

技术分享图片
HDU-3038-How Many Answers Are Wrong

这个题题目的废话比较多,这里简述一下大意:有M个数,不知道它们具体的值,但是知道某两个数之间(包括这两个数)的所有数之和,现在给出N个这样的区间和信息,需要判断有多少个这样的区间和与前边已知的区间和存在矛盾。例如给出区间和[1,4]为20,[3,4]为15,再给出[1,2]为30,显然这个[1,2]的值就有问题,它应该为20-15=5
View Code

 

  代码:

技术分享图片
#include <bits/stdc++.h>
using namespace std;
#define ri register int 
const int N=202000;
const int M=40000;
int n,m;
int val[N],fa[N],ans;
int find(int a)
{
    if(a!=fa[a])
    {
        int t=fa[a];
        fa[a]=find(fa[a]);
        val[a]+=val[t]; // 跟新 这个节点到 祖父的 权值 
    }
    return fa[a];
}
int main(){
    while(~scanf("%d%d",&n,&m))
    {
        ans=0;memset(val,0,sizeof val);
        for(ri i=0;i<=n;i++) fa[i]=i;
        for(ri i=1;i<=m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            a--;
            int l=find(a);
            int r=find(b);
            if(l!=r)
            {
                fa[l]=r;
                val[l]=-val[a]+c+val[b];   //跟新权值 
            }
            else
            {
                if(val[a]-val[b]!=c) ans++;// 解决问题 小的节点到 祖父的权值 大 
            }
        }
        printf("%d\n",ans);
    }
}
View Code

 

6

 

带权并查集

原文:https://www.cnblogs.com/Lamboofhome/p/11765200.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!