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

    带权并查集 

      就是合并的时候加个权值,找祖父时加个权值。

      对于闭区间的时候一定要变成开区间 a-1  ->B   很关键  下面 一定要 a--;将这个东西给连接起来。( 】这个样子

    题型:

      针对性的解决 一个很长的区间问题。 给出很多的小区间 ,来判断 这些小区间很前面的小区间冲不冲突。

    当元素太大的时候可以理想化。

      特别注意数组的超限问题 超过多少就没了。 

      利用map 《int,int》 等等的 一一对应表明。 就不会出现内存问题了,这个是动态的。// 栗子 奇偶的那道题。

       预处理: for(ri i=1;i<=n;i++)fa[i]=i;

      小注意 是 val【a】+=val【t】 这个t之前父亲的。 而且是+;

       找祖父

    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
    ",ans);
        }
    }
    View Code

    题目:相见减做判断, 找规律,本身就是开区间

    poj-1182-食物链
    
     
    
    食物链
    
    Time Limit: 1000MS         Memory Limit: 10000K
    Total Submissions: 92490         Accepted: 27910
    Description
    
    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。 
    现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。 
    有人用两种说法对这N个动物所构成的食物链关系进行描述: 
    第一种说法是"1 X Y",表示X和Y是同类。 
    第二种说法是"2 X Y",表示X吃Y。 
    此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 
    1) 当前的话与前面的某些真的话冲突,就是假话; 
    2) 当前的话中X或Y比N大,就是假话; 
    3) 当前的话表示X吃X,就是假话。 
    你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。 
    
    Input
    
    第一行是两个整数N和K,以一个空格分隔。 
    以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 
    若D=1,则表示X和Y是同类。 
    若D=2,则表示X吃Y。
    
    Output
    
    只有一个整数,表示假话的数目。
    
    Sample Input
    
    100 7
    1 101 1 
    2 1 2
    2 2 3 
    2 3 3 
    1 1 3 
    2 3 1 
    1 5 5
    Sample Output
    
    3
    View Code

    代码:

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<stack>
    using namespace std;
    const int M = 10005;
    const int N = 50050;
    #define ri register int 
    int fa[N],val[N];
    int find(int a)
    {
        if(a!=fa[a])
        {
            int t=fa[a];
            fa[a]=find(fa[a]);
            val[a]=(val[a]+val[t])%3;
        }
        return fa[a];
    }
    int n,m,ans;
    int main(){
        scanf("%d%d",&n,&m);
        for(ri i=1;i<=n;i++) fa[i]=i;
        for(ri i=1;i<=m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&c,&a,&b);
            if(a>n||b>n||(a==b&&c==2)) 
            { 
             ans++;continue;
            }
            int l=find(a);
            int r=find(b);
            if(l!=r)
            {
                fa[l]=r;
                val[l]=(val[b]+c-1-val[a]+3)%3;
            }
            else{
                if((val[a]-val[b]+3)%3!=(c-1)) ans++;
            }
        }
        printf("%d
    ",ans);
    }  
    View Code

    1

  • 相关阅读:
    demo
    Git
    rest-framework框架 -- 认证权限流程源码
    sublime
    restful 协议 +面试
    Django的CBV
    vue 之 vue-router
    vue 之node.js 02
    浏览器内核
    安装apache+php+mysql
  • 原文地址:https://www.cnblogs.com/Lamboofhome/p/11765200.html
Copyright © 2011-2022 走看看