笔试题记

通讯软件中,群里面转发消息可以使得一条消息扩散到多群,假设群数为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;
}
posted @ 2019-11-03 21:25  __Blog  阅读(79)  评论(0)    收藏  举报