Simple disjoint-set tree simple application hdu1232

Disjoint-set, the idea is to use the tree
Title: Investigation province town traffic, urban roads to get existing tables, the table lists the cities and towns each road directly connected. Target provincial government "Smooth Traffic Project" is to make the province between any two towns can implement traffic (but not necessarily directly connected to the road, as long as you can reach each other indirectly through road). Minimum asked how many roads also need to build?

Input help: test input contains several test cases. Each test case is given row of the first two positive integers, are the number of towns N (<1000) and road number M; M rows corresponding to the next M path, each row is given a pair of positive integers, respectively, the number two towns in direct communication path. For simplicity, the town numbered from 1 to N.
Note: number of roads may be communicated between the two cities, ie
. 3. 3
. 1 2
. 1 2
2. 1
This input is valid
when N is 0, an input end, the use cases are not processed.

Brief idea, if the two towns to build a road to a town as a child, as a parent node.
Every time you type two towns, we need to find the root node, comparing the root, so as to ensure that the two trees are independent tree, are not connected,
if two different root, on the combination of two root nodes. Merged into a tree. So all of this tree has a root node, that is, all nodes can reach each other. Finally, the number of root calculation n, n-1 is the minimum path required.

It also used the path compression, that is, when to find the root node, all the nodes under the root node, the root node is connected to the maximum.

#include <iostream>
#include<iomanip>
using namespace std;
int pra[1001] = {0};
int find(int root)//findroot函数,用于查找输入数值的根。并压缩路径
{
	int son, temp;
	son = root;
	while (root != pra[root])//寻找最大根
	{
		root = pra[root];
	}
	while (root != pra[root])//压缩路径的方式,将输入值与之后的跟直接连到最大根处;
	{
		temp = pra[son];
		pra[son] = root;
		son = temp;
	}
	return root;//返回最大根
}
void unite(int x, int y)//根的连接
{
	x = find(x);//找到x和y的最大根;
	y = find(y);
	if (x != y)//如果两个的最大根不相同,那么就将其中一个最大根作为子根连接到一个最大根,根的合并
	{
		pra[x] = y;
	}
}
int main()
{
	int n, k;
	int num;
	while (cin >> n)
	{
		if (n == 0) break;
		else 
		{
			cin >> k;
			num = n - 1;
			for (int i = 1; i <= n; i++)
				pra[i] = i;
			for (int i = 1; i <= k; i++)
			{
				int x, y;
				cin >> x >> y;
				unite(x, y);
			}
			for (int i = 1; i <= n; i++)
			{
				if (pra[i] != i)  num--;//遍历边的条数,计算最少要几条边
			}
			cout << num << endl;
		}
	}
}
Published 17 original articles · won praise 1 · views 3433

Guess you like

Origin blog.csdn.net/weixin_43983570/article/details/90549814