zoukankan      html  css  js  c++  java
  • 带权并查集 模板 HDU

    https://vjudge.net/problem/HDU-3038

    TT 写一串数字,对 FF 不可见
    FF 选择一个区间(会重复操作), TT 把这个区间的和告诉 FF,然后,一些和是不正确的,所以,有一些答案是矛盾的,根据这些矛盾求出答案错误的个数。
    注意两点:1、TT 给的一个 和 是正确的,如果它与之前给的 和 不矛盾。
    2、FF 发现一个与之前矛盾的 和 之后,该 和 不再参与之后的分析,直接被抛弃了。

    题意:给出区间[1,n],下面有m组数据,l r v区间[l,r]之和为v,每输入一组数据,判断此组条件是否与前面冲突 ,最后输出与前面冲突的数据的个数.
    比如 [1 5]区间和为100 然后后面给出区间[1,2]的和为 200 那肯定就是有问题的了。

    博客:https://www.cnblogs.com/liyinggang/p/5327055.html

    https://blog.csdn.net/yjr3426619/article/details/82315133?tdsourcetag=s_pcqq_aiomsg

    首先要先知道带权路径压缩的写法:

    int find(int x){
        if(pre[x]!=x){
            int y = pre[x];
            pre[x] = find(pre[x]);
            sum[x] += sum[y];
        }
        return pre[x];
    }

    还有带权并查集合并:

    pre[fa] = fb;
    sum[fa] = -sum[a] + s + sum[b] ;

    这题我们利用一个sum[]数组保存从某点到其祖先节点距离。
    通过处理,带权并查集每个节点的sum值都是其指向父亲节点的权值
    中间如果经历过了路径压缩,就是指向祖先的权值

    注意,给出区间的 L 和 R可能相同,而就无法用并查集这个数据结构来做了,所以存入时要把 L- - 或者R ++

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <string>
    #include <set>
    #include <map>
    #include <stack>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #define INF (1<<30)
    using namespace std;
    
    const int maxn = 2e5+7;
    int sum[maxn];
    int pre[maxn];
    
    int find(int x){
        if(pre[x]!=x){
            int y = pre[x];
            pre[x] = find(pre[x]);
            sum[x] += sum[y];
        }
        return pre[x];
    }
    
    int main(){
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF){
            for(int i=0; i<=n+1; i++){
                pre[i] = i;
                sum[i] = 0;
            }
            int fa,fb,a,b,s,ans=0;
            while(m--){
                scanf("%d%d%d",&a,&b,&s);
                b++;
                fa = find(a);
                fb = find(b);
                if(fa==fb){
                    if(sum[a]!=s+sum[b]){
                        ans++;
                    }
                }
                else{
                    pre[fa] = fb;
                    sum[fa] = -sum[a] + s + sum[b] ;
                }
            }
            printf("%d
    ", ans);
        }
    }
  • 相关阅读:
    LeetCode 18. 4Sum (四数之和)
    开运算、闭运算、形态学梯度、顶帽、黑帽
    膨胀和腐蚀
    四种滤波方式
    关于平滑处理及图像滤波与滤波器
    27、简述redis的有哪几种持久化策略及比较?
    26、redis中默认有多少个哈希槽?
    25、如何实现redis集群?
    大聊Python----Select解析
    大聊Python----IO口多路复用
  • 原文地址:https://www.cnblogs.com/-Zzz-/p/11469812.html
Copyright © 2011-2022 走看看