菜鸡奋斗路05-树8 File Transfer

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 (2N104), 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 kcomponents." 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.
作者: 陈越
单位: 浙江大学
时间限制: 150ms
内存限制: 64MB
代码长度限制: 16KB


个人分析:

题目说的是:现在有一堆电脑,它们互相之间初始没有连接成网,现在根据输入进行连接,且边连接(I c1 c2)边检查(C c1 c2)特定电脑之间有没有接好。如果接好了,就输出yes,反之no。最后,需要判断这堆电脑有几个不相连的子集,如果是一个那就是直接全连通了。

很明显的考察并查集操作的题目,课件教的用树来表示子集。由于每个电脑(结点)信息只用一个数字表示,我们不需要建立特殊结点结构体,直接用数组(结点数值=数组下标=结点地址;数组数值=父结点地址(下标)=父结点数值)即可。

代码如下:

#include<stdio.h>
#define Maxsize 10000


//初始化,各个结点均为头结点,头结点数组值赋为-1(也就是一开始的 负树总结点数) 
void Initialize(int T[],int n)
{
	int i;
	for(i=0;i<n;i++)
	{
		T[i]=-1;
	}
}
//联合,将倆树按秩合并
void Union(int T[],int Root1,int Root2)
{
	if(T[Root1]>T[Root2])
	{
		T[Root2]+=T[Root1];
		T[Root1]=Root2;       //将小树的头结点指向大树,大树根结点赋值为负二者总结点数 
	}
	else
	{
		T[Root1]+=T[Root2]; 
		T[Root2]=Root1; 	
	}	
} 
//查找,找到当前结点的根结点
int Find(int T[],int X)
{
	for(;T[X]>=0;X=T[X]);
	return X;
} 
//连接俩台计算机,先找到俩元素各自所在的集合根结点,再将二者联合 
void Input_connection(int T[])
{
	int u,v;
	int Root1,Root2;
	scanf("%d %d",&u,&v);
	getchar();
	Root1=Find(T,u-1);
	Root2=Find(T,v-1);
	if(Root1!=Root2)
		Union(T,Root1,Root2);
} 
//检查俩台计算机是否连接,到俩元素各自所在的集合根结点,对比是否相同 
void Check_connection(int T[])
{
	int u,v;
	int Root1,Root2;
	scanf("%d %d",&u,&v);
	getchar();
	Root1=Find(T,u-1);  //数组下标从0开始,输入从1开始,这里转换一下
	Root2=Find(T,v-1);
	if(Root1==Root2)
		printf("yes\n");   //若两个结点所在树的根结点相同,两结点在同一树上(这不废话嘛...)
	else
		printf("no\n");
} 
//检查所有计算机是否完全连接
void Check_Tree(int T[],int n)
{	
	getchar();
	int counter=0;
	for(int i=0;i<n;i++)
	{
		if(T[i]<0)
			counter++;
	}
	if(counter==1)
		printf("The network is connected.\n");
	else
		printf("There are %d components.",counter);
} 

int main()
{
	int n;char in;       //in记录操作:连接or检查
	int Tree[Maxsize];     
	scanf("%d",&n);
	getchar();
	Initialize(Tree,n);    
	do{
		scanf("%c",&in);
		switch(in){
			case 'I': Input_connection(Tree);break;    //连接操作
			
			case 'C': Check_connection(Tree);break;     //检查连接操作
			
			case 'S': Check_Tree(Tree,n);break;     //检查子集数操作
		}
		
	}while(in!='S');    //输入S时跳出
	return 0;
}

总结:小小一个数组,,以前从没想过,它能表示:树,堆,队列,堆栈,并查集合。。。。等等。菜鸡觉得,这和数组元素顺序储存,且每个元素都有一个特定下标表示等特点,有很大关系。

首先,数组元素其实包含了两个值(元素值+数组下标(地址)),它不像链表必须通过遍历才能到达某个地址,因为其地址就是下标。

第二,上述一些数据结构,都可表示成数据密集的情况,用数组很划算(空间利用率高)。

第三。。。。。。。嗯。。。ZZZZZZZZ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值