zoukankan      html  css  js  c++  java
  • 并查集(union-find)算法

    定义 

      算法具体内容:https://www.cnblogs.com/tanxing/p/5600984.html

      算法简单介绍:此算法主要用于寻找两个对象之间是否有联系,可应用于寻找社交网络中,某两人是否有联系(有共同认识的人);或渗透系统中,判断此系统是否渗透。此算法分为联结和寻找两部分。

      联结:

        a和b联结,以a为根节点:即root(a)=a && root(b)=a;

        两联结体A和B结合(其中,A有3个元素A,A2,A3,root(A)=root(A2)=root(A3)=A; B有4个元素:B,B2,B3,B4,root(B)=root(B2)=root(B3)=root(B4)=B),由于B联结体元素更多,所以A联结体被并入B联结体即root(A)=B。

      寻找:  

        如果想知道啊a和b是否在同一联结体里(即a和b是否有联系),只需要比较root(a)是否等于root(b)。

      

    例题

    解答

      解题思路:记录每个联结体(connected components)的最大值。联结(union)时,比较两个联结体的最大值后,更新新联结体的最大值。

    .h:
    UCLASS()
    class ALGORITHM_API AAlgorithmExerciseTwo : public AActor
    {
        GENERATED_BODY()
        
    public:    
        // Sets default values for this actor's properties
        AAlgorithmExerciseTwo();
    
        // Called every frame
        virtual void Tick(float DeltaTime) override;
    
        //构造数组
        void InitIdArray(int N);
        //寻找根节点
        int Root(int i);
        //检查p,q是否相连
        bool Connected(int p, int q);
        //链接p和q
        void Union(int p, int q);
        //找小组里的最大值
        int FindMax(int i);
    
    protected:
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;
    
    public:
    
    private:
    
        TArray<int> ID;
        TArray<int> SizeOfID;
        //记录并及时更新每个小组的最大值,即可完成查最大值的任务
        TArray<int> MaxOfID;
    
    };
    
    .cpp:
    
    // Sets default values
    AAlgorithmExerciseTwo::AAlgorithmExerciseTwo()
    {
         // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
    
    }
    
    // Called when the game starts or when spawned
    void AAlgorithmExerciseTwo::BeginPlay()
    {
        Super::BeginPlay();
        //测试
        InitIdArray(10);
        Union(1, 2);
        Union(6, 9);
        Union(1, 6);
        UKismetSystemLibrary::PrintString(this, "Root: " + FString::FromInt(Root(9)));
        UKismetSystemLibrary::PrintString(this, "Max: " + FString::FromInt(FindMax(1)));
    }
    
    // Called every frame
    void AAlgorithmExerciseTwo::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);
    
    }
    
    void AAlgorithmExerciseTwo::InitIdArray(int N)
    {
        //填充数组
        for (int i = 0; i < N; ++i)
        {
            ID.Add(i);
            //一开始,自己就是最大的
            MaxOfID.Add(i);
            //一开始只有自己一个
            SizeOfID.Add(1);
            
        }
    }
    //寻找根节点
    int AAlgorithmExerciseTwo::Root(int i)
    {
        while (i != ID[i])
        {
            ID[i] = ID[ID[i]];
            i = ID[i];
        }
        return i;
    }
    //检查p,q是否相连
    bool AAlgorithmExerciseTwo::Connected(int p, int q)
    {
        return Root(p) == Root(q);
    }
    //链接p和q
    void AAlgorithmExerciseTwo::Union(int p, int q)
    {
        int i = Root(p);
        int j = Root(q);
        //如果i==j,说明p,q已经连接了
        if (i == j) return;
        //谁大,则最大值取谁
        MaxOfID[i] < MaxOfID[j] ? MaxOfID[i] = MaxOfID[j] : MaxOfID[j] = MaxOfID[i];
        //大树吃小树:Link root of smaller tree to root of larger tree. 
        //注意:判断一棵树的大小,是根据它含有的子物体数量,而不是树的高矮来判断。
        if (SizeOfID[i] < SizeOfID[j])
        {
            ID[i] = j;
            SizeOfID[j] += SizeOfID[i];
        }
        else
        {
            ID[j] = i;
            SizeOfID[i] += SizeOfID[j];
        }
    }
    //返回小组中的最大值
    int AAlgorithmExerciseTwo::FindMax(int i)
    {
        return MaxOfID[i];
    }
  • 相关阅读:
    (Vue中)cehart在同一个dom上画图图切换时饼图有折线图的坐标系
    linux(centos7)修改服务器时间
    centos6 yum源不能使用
    Linux 使用 history 来减少重复命令的几个实用技巧。
    7个Shell 拿来就用脚本实例!
    keepalived的配置解析&安装与爬坑
    linux最全命令使用手册
    linux各种误删文件恢复方法(经典强推)
    位运算符
    SQL 书写、执行顺序
  • 原文地址:https://www.cnblogs.com/mcomco/p/10039134.html
Copyright © 2011-2022 走看看