05-树8 File Transfer (25分)

We have a network of computers and a list of bi-directional connections. Each of these connections allows a file transfer from one computer to another. Is it possible to send a file from any computer on the network to any other?

Input Specification:

Each input file contains one test case. For each test case, the first line contains NNN (2≤N≤1042\le N\le 10^42N104), the total number of computers in a network. Each computer in the network is then represented by a positive integer between 1 and NNN. Then in the following lines, the input is given in the format:

I c1 c2

where I stands for inputting a connection between c1 and c2; or

C c1 c2

where C stands for checking if it is possible to transfer files between c1 and c2; or

S

where S stands for stopping this case.

Output Specification:

For each C case, print in one line the word "yes" or "no" if it is possible or impossible to transfer files between c1 and c2, respectively. At the end of each case, print in one line "The network is connected." if there is a path between any pair of computers; or "There are k components." where k is the number of connected components in this network.

Sample Input 1:

5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S

Sample Output 1:

no
no
yes
There are 2 components.

Sample Input 2:

5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
I 1 3
C 1 5
S

Sample Output 2:

no
no
yes
yes
The network is connected.


并查集

#include 
#include 
int parent[10000];	//parent[0]不用,因为题目中N是从1开始的,否则会数组越界

////非递归 普通
//int Find(int x) {
//	while(parent[x] > 0)
//		x = parent[x];
//	return x;
//}

////递归 普通
//int Find(int x)
//{
//	if(parent[x] < 0)
//		return x;
//	else
//		return Find(parent[x]);
//}
//
////非递归 路径压缩
//int CollapsingFind(int i)
//{
//	int j;
//	for(j = i; parent[j] >= 0; j = parent[j]); //搜索根
//	while(i != j)
//	{
//		int temp = parent[i];
//		parent[i] = j;
//		i = temp;
//	}
//	return j;
//}

//递归 路径压缩 
int Find(int x){
	if(parent[x] < 0)
		return x;
	else
		return parent[x] = Find( parent[x] );   //先改变树的结构,再返回根结点
}

//极简Union
//void Union(int a, int b) {
//	int faA = Find(a);
//	int faB = Find(b);
//	parent[faA] = faB;
//}

//按秩归并(按规模)
void Union(int a, int b) {
	int faA = Find(a);
	int faB = Find(b);
	if(parent[faA] > parent[faB]){
		//这两句话不能颠倒,必须先改变树的规模,再连接树,错误原因2
		//倒过来后,导致根结点值大于0,使Find无限循环(递归的会溢出)
		parent[faB] += parent[faA];
		parent[faA] = faB;
	}
	else {
		parent[faA] += parent[faB];
		parent[faB] = faA;
	}
}

//按秩归并(按树高)
//void Union(int a, int b) {
//	int faA = Find(a);
//	int faB = Find(b);
//	if(parent[faA] > parent[faB])
//		parent[faA] = faB;
//	else {
//		if(parent[faA] > parent[faB])
//			parent[faA]--;
//		parent[faB] = faA;
//	}
//}
void InputConnection(){
	int a, b;
	scanf("%d %d\n", &a, &b);  //\n能够防止in接收到它
	Union(a, b);
}
void CheckConnection(){
	int a, b;
	scanf("%d %d\n", &a, &b);
	int faA = Find(a);
	int faB = Find(b);
	if(faA == faB)
		printf("yes\n");
	else
		printf("no\n");
}
void CheckNetwork(int n){
	int cnt = 0;
	for(int i = 1; i <= n; i++){     //从1开始,错误原因
		if(parent[i] < 0)
			cnt++;
	}
	if(cnt == 1)
		printf("The network is connected.");
	else
		printf("There are %d components.", cnt);
}
int main(){
	int n;
	char in;
	scanf("%d\n", &n);	//能够忽略换行符,防止in接收
	//初始化parent
	for(int i = 1; i <= n; i++)		//从1开始,错误原因
		parent[i] = -1;

	do {
		scanf("%c", &in);
		switch (in) {
		case 'I' : InputConnection();break;
		case 'C' : CheckConnection();break;
		case 'S' : CheckNetwork(n);break;
		}
	} while( in != 'S' );
	system("pause");
	return 0;
}



你可能感兴趣的:(PTA,并查集)