并查集模板

并查集模板 

并查集:通过压缩路径使查找更加迅速快捷,在大数据量上效果更加明显

递归实现:

int par[max_n];
int Rank[max_n];

void init(int n)    //初始化父元素
{
    for(int i=0; i<n; i++)
    {
        par[i] = i;
        Rank[i] = 0;
    }
}


int find_par(int n)    //寻找根节点
{
    if(par[n] == n) return n;
    return par[n] = find_par(par[n]);
}

void unit_par(int a, int b)    //合并集合
{
    a = find_par(a);
    b = find_par(b);
    if(a == b) return;
    if(Rank[a] < Rank[b]) par[a] = b;   //b 节点更高,将a集合链接到pb
    else 
    {
        par[b] = a;
        if(Rank[a] == Rank[b]) Rank[a]++;
    }
}

bool same(int a, int b)    //判断是否属于同一集合
{
    return find_par(a) == find_par(b);
}

循环实现:


int par[max_n];
int Rank[max_n];

void init(int n)    //初始化父元素
{
    for(int i=0; i<n; i++)
    {
        par[i] = i;
        Rank[i] = 0;
    }
}

void find_par(int n)   //查找父节点
{
    int nn = n;
    while(par[n] != n)
    {
        n = par[n];
    }
    int x = nn;
    while(par[nn] != n)
    {
        x = par[nn];
        par[nn] = n;
        nn = x; 
    }
}


void unit_par(int a, int b)    //合并集合
{
    a = find_par(a);
    b = find_par(b);
    if(a == b) return;
    if(Rank[a] < Rank[b]) par[a] = b;   //b 节点更高,将a集合链接到pb
    else 
    {
        par[b] = a;
        if(Rank[a] == Rank[b]) Rank[a]++;
    }
}

bool same(int a, int b)    //判断是否属于同一集合
{
    return find_par(a) == find_par(b);
}




变形应用:


题目链接:codevs 2639 约会计划



#include <iostream>
#include <cstdio>
#include <map>
#include <string>


using namespace std;


map<string, string> par;
map<string, int> Rank;

string Find(string s)
{
    if(par[s] == s) return s;
    return par[s] = Find(par[s]);
}

void unit_par(string a, string b)
{
    a = Find(a);
    b = Find(b);
    if(a == b) return;
    else
    {

        if(Rank[a] > Rank[b]) par[b] = a;
        else
        {
            par[a] = b;
            if(Rank[a] == Rank[b]) Rank[b]++;
        }
    }
    return;
}

bool same(string a, string b)
{
    return Find(a) == Find(b);
}

int main()
{
    int n, m, p;
    scanf("%d%d%d", &n, &m, &p);
    string s, ss;
    while(n--)
    {
        cin >> s;
        par[s] = s;
        Rank[s] = 0;
    }
    while(m--)
    {
        cin >> s >> ss;
        s = Find(s);
        ss = Find(ss);
        unit_par(s, ss);
    }
    while(p--)
    {
        cin >> s >> ss;
        if(same(s,ss)) printf("safe\n");
        else printf("cc cry\n");
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值