05-树8 File Transfer(浙大数据结构PTA习题)

05-树8 File Transfer        分数 25        作者 陈越        单位 浙江大学

Question:

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 N (2≤N≤104), the total number of computers in a network. Each computer in the network is then represented by a positive integer between 1 and N. 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.

代码长度限制:16 KB        内存限制:64 MB

Go (go)时间限制:400 ms        Java (javac)时间限制:400 ms

Python (python3)时间限制:400 ms        其他编译器时间限制:150 ms

题目解析:

该题的本质主要考察集合的查找与合并问题,但对时间的限制比较严格。因此在合并的过程中,需要尽量使得小集合合并到大集合中;此外在查找过程中还需要对集合进行路径的压缩,压缩的思路如下图所示。

参考代码: 

# include<stdio.h>

typedef int ElementType;

void Connect(ElementType Set[],ElementType a, ElementType b);
void Check(ElementType Set[],ElementType a, ElementType b);
ElementType FindRoot(ElementType Set[],ElementType X);
void PrintSetComponent(ElementType Set[],int N);

int main(){
	int N;
	scanf("%d",&N);
	getchar();
	// 接收一个数组,数组从下标1开始存储
	int i,Set[N+1];
	for(i=1;i<=N;i++)Set[i] = -1; 
	// 开始连接或检查
	char op; 
	int a,b;
	while((op=getchar())!='S'){
		scanf("%d %d",&a,&b);
		getchar();
		if(op=='C'){
			Check(Set,a,b);
		}else if(op=='I'){
			Connect(Set,a,b);
		}
	}
	// 输出一共包含几个部分 
	PrintSetComponent(Set,N);
	return 0;
}


// 合并两个集合,将小集合合并到大集合上 
void Connect(ElementType Set[],ElementType a, ElementType b){
	ElementType root_a = FindRoot(Set,a);
	ElementType root_b = FindRoot(Set,b);
	if(Set[root_a]<Set[root_b]){
		// a集合更大,将b集合合并到a集合中
		Set[root_a] += Set[root_b];
		Set[root_b] = root_a;
		
	}else{
		// b集合更大或一样大,将a集合合并到b集合中
		Set[root_b] += Set[root_a]; 
		Set[root_a] = root_b; 
	}
	return;
}

// 检查两个元素是否同属于一个集合
void Check(ElementType Set[],ElementType a, ElementType b){
	if(FindRoot(Set,a) == FindRoot(Set,b))printf("yes\n");
	else printf("no\n"); 
} 

// 根据元素,查找其所属集合的根结点返回其下标,并在此过程中进行集合架构的调整 
ElementType FindRoot(ElementType Set[],ElementType X){
	// tmp为父结点下标 或 X为根结点时其为集合大小的相反数 
	int tmp = Set[X];
	if(tmp<0)return X;
	// 若父结点位置元素大于0 
	while(Set[tmp]>0){
		Set[X] = Set[tmp];
		tmp = Set[X];
	}
	return tmp; 
} 

// 输出一共包含几个不同的集合
void PrintSetComponent(ElementType Set[],int N){
	int i,count = 0;
	for(i=1;i<=N;i++){
		if(Set[i]<0)count++;
	}
	if(count==1)printf("The network is connected.\n");
	else printf("There are %d components.\n",count);
	return;
} 

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值