• 带权并查集浅谈


    笔者最近刷到了一道带权并查集的题目,当做入门博客写一篇学习笔记吧。

    题目链接

    题目中要求求距离+换爹,很显然,暴力的dfs在20000的数据下绝对会被卡的。

    自然想到,什么数据结构可以快速维护父子关系?

    显然有并查集。

    那么,我们要做的就是修改并查集,使它能够维护距离了。

    那么,我们在每一次更新父亲(路径压缩)的时候更新距离。

    先来看最基本的find函数:

    inline int find(int x){
        return x==f[x]?x:f[x]=find(f[x]);
    }

    我们要在这时候维护距离dis的改变。

    于是,我们先记录下路径压缩前的父亲。

    然后压缩。

    返回的时候,当前的结点要累加之前的距离即可。

    代码:

    inline int find(int x){
        if(x==f[x])return x;
        int t=f[x];//记录之前父亲 
        f[x]=find(f[x]);//并查集find 
        dis[x]+=dis[t];//累加距离 
        return f[x];
    }

    对于多组训我,切记清空数组。并查集的初始化不要忘记。

    将dis数组初始化为0,f数组照常赋值成自己。

    对于第一个操作,直接认爹,然后更新距离。

    所以,对于第二个E操作,在询问的时候要find一下,以便于更新之前没有更新的距离。之后直接输出即可。

    注意,dis[x]维护的是x到根的距离。

    并查集是树形结构。

    总代码:

    #include<cstdio>//加权并查集 
    #include<iostream>
    #include<cstring>
    using namespace std;
    int dis[50000],f[50000];
    int n,x,y,t;
    char s[50];
    /*st
    struct node{
        int next,to;
    }; 
    head[5000];
    inline void add(int x,int y){
        e[++tot].to=y;
        e[tot].next=head[x];
        head[x]=tot;
    }*/
    inline int abs(int x){return x<0?-x:x;}
    inline void read(int &x){
        int s=0,w=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){
            if(ch=='-')w=-1;
            ch=getchar();
        }while(ch>='0'&&ch<='9'){
            s=(s<<1)+(s<<3)+(ch^48);
            ch=getchar();
        }x=s*w;
    }
    inline int find(int x){
        if(x==f[x])return x;
        int t=f[x];//记录之前父亲 
        f[x]=find(f[x]);//并查集find 
        dis[x]+=dis[t];//累加距离 
        return f[x];
    }
    inline void init(){
        memset(dis,0,sizeof(dis));
        for(int i=1;i<=n;++i)f[i]=i;
    }
    int main(){
        read(t);
        while(t--){
            read(n);
            init();
            while(1){
                cin>>s;
                if(s[0]=='O')break;
                if(s[0]=='I'){
                    read(x);
                    read(y);
                    f[x]=y;
                    dis[x]+=abs(x-y)%1000;
                }else{
                    read(x);
                    find(x);
                    printf("%d
    ",dis[x]);
                }
            }
        }
        return 0;
    }

    留一道例题,笔者之后补题解。

    题目链接(种类并查集)

    题解

    例题2

  • 相关阅读:
    没有什么,开发ASP.NET时随便写写,想到什么写什么
    MS SQL Server带有时间的记录怎样查询
    给RadioButtonList绑定Selected的值
    在GridView控件内文本框实现TextChanged事件
    MS SQL Server递归查询
    ASP.NET MVC使用jQuery无刷新上传
    MySQL 慢查询操作梳理
    ubuntu系统下防火墙简单使用
    crontab日常使用梳理
    ubuntu下nginx+php5的部署
  • 原文地址:https://www.cnblogs.com/h-lka/p/11158449.html
Copyright © 2020-2023  润新知