英雄算法7月17号

英雄算法7月17号

2316

class CheckSet {
    //小弟->大哥->头头
private:
    int arr[100001]; 
public:
    CheckSet() {
        for(int i = 0; i < 100001; ++i) {
            arr[i] = i;
        }
    }
    int find(int num) {
        return arr[num] = (num == arr[num]) ? num : find(arr[num]);//找到num的头头,如果没找到,那就继续找。同时将沿途所有人都指向最终找到的头头,削减大哥的实力。
    }
    void Union(int num1, int num2) {
        int faIdx1 = find(num1);//找到num1的头头
        int faIdx2 = find(num2);//找到num2的头头
        if(faIdx1 != faIdx2) {//他们不在同一个帮派
            arr[faIdx1] = faIdx2;//让num1的头头变成num2的头头,完成叛变
        }
    }
};
class Solution {
public:
    long long countPairs(int n, vector<vector<int>>& edges) {
        CheckSet c = CheckSet();//建立并查集
        for(auto& x: edges) {//遍历图的所有节点,建立并查集         
            c.Union(x[0], x[1]);//建立区块结构,连接每一个区块间的内部成员
        }
        unordered_map<long,long> hash;
        for(int i = 0; i < n; ++i) {//找到每一个连通区块的根节点,并且统计每个区块的节点数量
            ++hash[c.find(i)];
        }
        long long ans = 0;
        for(auto iter = hash.begin(); iter != hash.end(); ++iter) {
            ans += (iter->second) * (n - iter->second);//计算结果
        }
        return ans/2;
    }
};

思路

并查集

并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。

举个例子:

我们眼前有一群人,而这群人可以统一用一个数组来表示。而这群人又会拉帮结派,形成不同的团体。每个团体又会有自己的领袖,也就是头头,为了在数组中表示头头,我们只需要让所有的小弟指向大哥,大哥在指向头头;或者所有人都指向头头即可。如果遇到帮派吞并,那么只要让新帮派的所有成员指向其他帮派的头头即可完成吞并。

有了并查集对象(本文是:CheckSet

  • find
    • 找到某个人的头头
    • 寻找的过程中,将所有人都指向头头,而不是大哥
  • Union
    • 让两个人指向同一个头头
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值