并查集-百度笔试题

百度笔试题

百度全体员工玩分组游戏,前面五分钟大家分头找队友,并将每个人找到的队友信息汇报给主持人,如果AB是队友,BC是队友,那么AC也是队友;接着主持人不断地随机抽取两个人,希望判断二者是否为队友。请设计一个计算机程序辅助主持人判断两个人是否为队友,说明程序的关键算法,不需要代码实现。

例如:<小明,小王><小军,小王><小丽,小李>是队友,那么小军和小明是队友,小军和小丽不是队友。

分析:考查并查集。

代码:

#include<iostream>
#define MAXNUM 100
using namespace std;
static string name[MAXNUM];
static int group[MAXNUM];
static int rank[MAXNUM];
void make_set()
{
for(int i=0;i<MAXNUM;i++)
{
group[i]=i;
rank[i]=0;
}
}
int findGroup(int i)
{
if(group[i]==i)
{
return group[i];
}
group[i]=findGroup(group[i]);
}
int myfindGroup(int i)
{
return group[i];
}
void union1(int i,int j)
{
int g1=findGroup(group[i]);
int g2=findGroup(group[j]);
//cout<<"g1="<<g1<<" "<<"g2="<<g2<<endl;
if(rank[g1]>rank[g2])
{
group[j]=g1;
}
else
{
group[i]=g2;
if(rank[g1]==rank[g2])
{
rank[g2]++;
}
}
}
bool judgeGroup(string name1,string name2)
{
int index1=0,index2=0;
for(int i=0;i<MAXNUM;i++)
{
if(name1==name[i])
{
index1=i;
break;
}
}
for(int j=0;j<MAXNUM;j++)
{
if(name2==name[j])
{
index2=j;
break;
}
}
//cout<<group[2]<<endl;
if(myfindGroup(index1)==myfindGroup(index2))
{
//cout<<index1<<" "<<findGroup(index1)<<endl;
//cout<<index2<<" "<<findGroup(index2)<<endl;
return true;
}
return false;
}
int main()
{
name[0]="小明";
name[1]="小王";
name[2]="小军";
name[3]="小丽";
name[4]="小李";
make_set();
union1(0,1);
union1(2,1);
union1(3,4);
for(int i=0;i<5;i++)
{
cout<<group[i]<<endl;
}
string name1,name2;
cin>>name1;
cin>>name2;
if(judgeGroup(name1,name2))
{
cout<<name1<<"和"<<name2<<"是队友."<<endl;
}
else
{
cout<<name1<<"和"<<name2<<"不是队友"<<endl;
}
system("pause");
return 0;
}

说明:

group数组用于保存每个节点的父节点。初始时,每个节点单独成为一棵树,每个节点的父节点均是本身。随着树的合并,要不断的修改group数组。

rank数组用于保存以每个节点为根节点的子树的高度。初始时,设置值为0。随着合并,要不断修改此数组数据。合并时,倾向于以高度较高的子树的根为合并后的树的根,以保证树的高度不至于过高。

 

参考:

http://www.cnblogs.com/yangyh/archive/2010/05/30/1747509.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值