用并查集求朋友圈数目

小米的一道面试题:

假如已知有n个人和m对好友关系,如果两个人是直接或者间接有好友关系,则认为他们属于同一个朋友圈。写程序判断里面有多少朋友圈。
例如:
n = 5, m = 3  r = {(1,2), (2, 3), (4, 5)}  1 2 3 是一个朋友圈, 4 5 是一个朋友圈。
所以输出是2


这道题用并查集来求解就非常容易了。关于并查集的内容,这篇文章写得非常好:

http://blog.csdn.net/dm_vincent/article/details/7655764#reply

根据这篇文章,写了一个求解方法,代码如下:

class UnionFind {
public:
	UnionFind(int n) : cnt(n)
	{
		id = new int[n];
		for (int i = 0; i < n; i++)
			id[i] = i;

		size = new int[n];
		for (int i = 0; i < n; i++)
			size[i] = 1;
	}
	
	~UnionFind()
	{
		delete[] id;
		delete[] size;
	}

	// 返回连通组的个数
	int count()
	{
		return cnt;
	}

	// 查找一个节点属于哪个组
	int findSet(int a)
	{
		if (id[a] == a)
			return a;
		else
			return id[a] = findSet(id[a]);	// 查找的同时提高节点的高度
	}

	bool isSameSet(int a, int b)
	{
		int x = findSet(a);	// 查找a的组号
		int y = findSet(b);	// 查找b的组号

		return x == y;		// 判断组号是否相同
	}

	void Union(int a, int b)
	{
		int x = findSet(a);
		int y = findSet(b);

		if (x != y)
		{
			if (size[x] < size[y])
			{
				id[x] = y;
				size[y] += size[x];
			}
			else
			{
				id[y] = x;
				size[x] += size[y];
			}

			cnt--;	// 合并后组的数量-1
		}
	}

private:
	int *id;
	int *size;
	int cnt;
};

int main()
{
	UnionFind friends(5);

	friends.Union(0, 1);
	friends.Union(1, 2);
	friends.Union(3, 4);

	cout << "朋友圈数目:" << friends.count() << endl;

	system("pause");
	return 0;
}

运行结果:


你可能感兴趣的:(用并查集求朋友圈数目)