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 <stdio.h>
#include <stdlib.h>
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;
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 这道题目是要求我们实现一个文件传输的功能。具体来说,我们需要实现一个形结构,其中每个节点代表一个文件夹或文件,每个节点包含一个名称和一个大小。我们需要支持以下操作: 1. 添加文件夹或文件 2. 删除文件夹或文件 3. 计算某个文件夹下所有文件的大小 4. 将某个文件夹下的所有文件复制到另一个文件夹中 我们可以使用递归的方式来实现这些操作。具体来说,对于添加和删除操作,我们可以先找到对应的节点,然后递归地添加或删除子节点。对于计算文件夹大小和复制文件夹操作,我们可以递归地遍历整个子,然后累加文件大小或复制文件。 需要注意的是,我们需要保证文件夹和文件的名称是唯一的,否则会出现冲突。另外,我们需要考虑如何处理文件夹的嵌套,即一个文件夹中包含另一个文件夹的情况。这时候我们可以使用递归的方式来处理。 ### 回答2: 题目:05-8 file transfer 题目描述: 在计算机网络中,经常需要把大文件解成若干个片进行传输。并且为了保证数据的可靠性和完整性,还需要通过校验和校验传输的片是否损坏。现在给定一份大文件,和一个校验和得列表,请你判断这个文件是否完整。 输入格式: 输入在第一行给出文件的大小(不超过$10^6$字节)——正整数。 第二行给出对应的校验和得列表——正整数不超过100的个位数所组成的列表,其长度不超过200。 输出格式: 如果校验通过,输出“File is complete.”;否则输出“File is incomplete.”。 算法思路: 首先根据给定的文件大小,判断文件是否可以被校验和的值列表所整除。如果可以整除,表示文件可能是完整的。接下来,计算给定的校验和列表的和(不包括得列表中的第一个值),如果该和可以被9整除,那么文件通过校验。 具体步骤: 1. 读取文件的大小和校验和得列表; 2. 判断文件大小是否可以被校验和值列表的和整除; 3. 计算校验和值列表(不包括第一个值)的和,判断是否可以被9整除; 4. 若上述两个条件均满足,则输出“File is complete.”,否则输出“File is incomplete.”。 算法实现: ```python file_size = int(input()) checksum_list = [int(x) for x in input().split()] if file_size % sum(checksum_list) == 0 and sum(checksum_list[1:]) % 9 == 0: print("File is complete.") else: print("File is incomplete.") ``` 算法复杂度析: 假设文件大小为N,校验和得列表的长度为M。该算法的时间复杂度为O(1),空间复杂度为O(M)。 ### 回答3: 题目:05-8 file transfer (25 ) 题目大意:有N个用户,每个用户可能属于不同的网络。每个用户知道属于他的网络的根节点的ID。现在给出一个用户列表和每个用户所在网络的根节点ID。用户和网络的根节点ID是从1到N编号的。然后给出M个操作,操作有两种类型:1.询问某个用户所在网络中的用户总数;2.把某两个用户所在的网络合并。请根据给定的用户列表和操作,输出每次询问的用户总数。 思路: 首先我们需要建立一个并查集,来记录每个用户所在的网络。 然后根据操作类型来进行不同的操作: 1.对于询问某个用户的操作,我们只需找到该用户所在的网络的根节点,然后返回该根节点所属的网络的用户总数。 2.对于合并某两个用户所在网络的操作,我们需要查找两个用户所在的网络的根节点,如果两个根节点不同,则将两个根节点合并,并更新用户总数。 具体实现: 1.定义并查集的类,包括初始化并查集、查询根节点、合并两个节点的方法。 2.按照操作顺序进行操作,针对不同操作类型进行不同处理。 3.对于查询操作,直接调用并查集类的查询根节点方法,输出根节点所属网络的用户总数。 4.对于合并操作,先调用并查集类的查询根节点方法,查找两个用户所在网络的根节点。如果根节点不同,则进行合并,并更新用户总数。 5.输出每次查询操作得到的用户总数。 代码实现: ```python # 定义并查集类 class UnionFind: def __init__(self, n): self.parent = [i for i in range(n + 1)] self.size = [1] * (n + 1) self.count = n def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def merge(self, x, y): root_x = self.find(x) root_y = self.find(y) if root_x != root_y: self.parent[root_x] = root_y self.size[root_y] += self.size[root_x] self.count -= 1 # 主函数 if __name__ == "__main__": N = int(input()) # 用户数 uf = UnionFind(N) # 创建并查集 for _ in range(N): user, root = map(int, input().split()) uf.merge(user, root) M = int(input()) # 操作数 result = [] for _ in range(M): op, user = map(int, input().split()) if op == 1: result.append(uf.size[uf.find(user)]) else: user1, user2 = map(int, input().split()) uf.merge(user1, user2) # 输出每次查询操作的结果 for res in result: print(res) ``` 这样就可以根据给定的用户列表和操作,输出每次询问的用户总数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值