笔试题记
通讯软件中,群里面转发消息可以使得一条消息扩散到多群,假设群数为m,其中一人把一条消息转发到自己群里,这些群的每个人又把消息转发到自己的所在群,这些群里面的每个人又将消息转发到他所在群,问所有群的所有人都转发一次之后,最后几人收到该消息(包括发消息的人)
输入描述:
发送第一天消息的人名
群组个数m
群组1成员人名列表
群组2成员人名列表
...
群组m成员人名列表
int find(int* pre,int k) //寻找k的根结点
{
if (pre[k] == k) return k; //我们以pre的值是否是自身下标来判断根结点
return pre[k] = find(pre,pre[k]); //递归路径压缩
}
void merge(int* pre,int* size,int a, int b) //合并集合
{
int t1 = find(pre,a); //找到a和b的根结点
int t2 = find(pre,b);
if (t1 != t2) {
pre[t1] = t2; //靠右,即把左边的集合变成右边的子集合
size[t2] = size[t1] + size[t2];
size[t1] = 0;
}
}
int main()
{
/*
0: A B C
1:B D
2: A E
3: F
*/
const char* arr[]= {
"A B C","B D","A E","F"};
int m = 4;
vector<string> name;
vector<vector<int>> vec;
string str;
for (auto i = 0; i < m; i++) {
stringstream input(arr[i]);
vector<int> vp;
while (input >> str) {
if (!name.empty()) {
auto pos = find(name.begin(), name.end(), str);
if (pos == name.end()) {
name.push_back(str);
vp.push_back(name.size()-1);
}
else {
vp.push_back(pos - name.begin());
}
}
else {
name.push_back(str);
vp.push_back(0);
}
}
vec.push_back(vp);
vp.clear();
}
shared_ptr<int> size(new int[name.size()]);
shared_ptr<int> pre(new int[name.size()]);
for (int i = 0; i < name.size(); i++) {
pre.get()[i] = i; //每个结点的父结点初始化为自己
size.get()[i] = 1;
}
for (auto i = 0;i < m; i++)
{
for (auto j = 0; j < vec[i].size() - 1; j++) {
merge(pre.get(),size.get(),vec[i][j], vec[i][j + 1]);
}
}
for (int i = 0; i < name.size(); i++) {
cout << pre.get()[i] << " ";
}
cout << endl;
for (int i = 0; i < name.size(); i++) {
cout << size.get()[i] << " ";
}
return 0;
}
浙公网安备 33010602011771号