【蓝桥杯每日一题】3.14 家谱

原题链接P2814 家谱 - 洛谷
解析参考P3367【模板】并查集

什么是并查集:

我们假定 f [ i ] f[i] f[i]表示第i个人的老大是谁。

现在,我们有甲,乙,丙打架了,甲做了乙的小弟。则有 f [ a ] f[a] f[a]= b b b,后来甲打赢了丙,那么丙就是甲的小弟了。有 f [ c ] = a f[c]=a f[c]=a,但是如果我们这样表示,丙不能直接知道乙是最大的大哥。所以我们必须直接让乙变成最大的老大,为了避免自己人打自己人,于是定义函数 f i n d ( ) find() find()

int find(int k){
    if(f[k]==k) return k;
    return find(f[k]);
}//find函数可以直接找到最大的老大

f[c]=find(a); //找到丙的最大的老大

这时,因为我们要路过他所有的上级,我们也可以顺便使寻找的途中经过的人的大哥也变成"最大的老大",于是进行路径压缩

//路径压缩
int find(int k){
    if(f[k]==k) return k;
    return f[k]==find(f[k]);
    /*
    也即;
    f[k]=find(f[k]);
    return f[k];
    */
}//递归版 find 函数

//循环版 find 函数
int find(int x){
    while(x!=f[x]) x=f[x]=f[f[x]];
    //让x 和x的老大变成统一变成最大的老大
    return x;
}

判断两个人的老大是否是同一个人,只需:

if(find(a)==find(b))

规定:

  • 一个人不能有两个老大
  • 当已经有老大的人臣服时,老大也将成为胜利的人的小弟

该题思路:

  • 题目中的father 便是上面说的老大
  • 利用STL中的map结构进行 < s t r i n g , s t r i n g > <string,string> <string,string>的映射

AC代码:

// 家谱 P2814
#include<bits/stdc++.h>
using namespace std;

map<string,string>g; //father son
string s,s1;

string find(string x)
{
    if(x!=g[x]) 
        g[x]=find(g[x]);
    return  g[x];
}
int main()
{
    char ch;
    cin>>ch;
    while(ch!='$')
    {
        cin>>s;
        if(ch=='#')
        {
            s1=s;
            if(g[s]=="") g[s]=s;
        }
        else if(ch=='+')
            g[s]=s1;
        else 
            cout<<s<<' '<<find(s)<<endl;    
        cin>>ch;
    }
    return 0;
}
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值