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 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.
题目思路:
实际上就是并查集,关键是要进行路径压缩,以下这个是何老师讲的方法没有进行路径压缩
#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAXN 10001
#define MINH -1
#define ElementType int
typedef struct{
ElementType Data;
float Parent;
}SetType;
SetType H[MAXN];//建立堆
void CreateSetType(int N)
{
for(int i = 0; i < N; i++)
{
H[i].Data = i+1;
H[i].Parent = -1;
}
}
int Find(SetType S[],ElementType X)
{
//在数组S中查找值为X的元素所属的集合
//MAXN为全局变量,为数组S的最大长度
int i;
for( i = 0; i < MAXN&&S[i].Data != X;i++);
if(i > MAXN){
return -1;//未找到X,返回-1
}
for(;S[i].Parent >=0; i = S[i].Parent);
return i;//找到X所属集合,返回树根节点在数组S中的下标
}
void Union(SetType S[], ElementType X1,ElementType X2)
{
int Root1,Root2;
Root1 = Find(S,X1);
Root2 = Find(S,X2);
if( Root1 != Root2 )
{
int root1,root2;
root1 = fabs(S[Root1].Parent);
root2 = fabs(S[Root2].Parent);
if( root1 >= root2 )
{
S[Root2].Parent = Root1;
S[Root1].Parent = S[Root1].Parent - 1;
}
else
{
S[Root1].Parent = Root2;
S[Root2].Parent = S[Root2].Parent - 1;
}
}
}
int main()
{
//读入节点数
int N;
//freopen("test.txt","r",stdin);//debug
scanf("%d",&N);
CreateSetType(N);
//看操作
char operation[10];
int a,b;
while(scanf("%s",operation) == 1)//还有数据输入就循环
{
if(strcmp(operation,"S")==0)break;//结束了,判断有几个集合
if(strcmp(operation,"C")==0)
{
scanf("%d %d",&a,&b);
if((Find(H,a)==Find(H,b)) && (Find(H,a) != -1))//根节点相同说明在一根树上
{
printf("yes\n");
}
else
{
printf("no\n");
}
}
if(strcmp(operation,"I")==0)
{
scanf("%d %d",&a,&b);
Union(H,a,b);
}
}
int num = 0;//统计树的个数
for(int i = 0; i < N; i++)
{
if(H[i].Parent < 0)
{
num++;
}
}
if(num==1)
{
printf("The network is connected.\n");
}
else
{
printf("There are %d components.\n",num);
}
return 0;
}
下面这个进行了路径压缩
#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAXN 10001
#define MINH -1
#define ElementType int
typedef struct{
ElementType Data;
float Parent;
}SetType;
SetType H[MAXN];//建立堆
void CreateSetType(int N)
{
for(int i = 0; i < N; i++)
{
H[i].Data = i+1;
H[i].Parent = -1;
}
}
int Find(SetType S[],ElementType X)
{
//在数组S中查找值为X的元素所属的集合
//MAXN为全局变量,为数组S的最大长度
int root;
root = X - 1;
while(S[root].Parent >= 0)
{
root = S[root].Parent;
}
return root;
}
void Union(SetType S[], ElementType X1,ElementType X2)
{
int Root1,Root2;
Root1 = Find(S,X1);
Root2 = Find(S,X2);
if( Root1 != Root2 )
{
int root1,root2;
root1 = fabs(S[Root1].Parent);
root2 = fabs(S[Root2].Parent);
if( root1 >= root2 )
{
S[Root2].Parent = Root1;
S[Root1].Parent = S[Root1].Parent - 1;
}
else
{
S[Root1].Parent = Root2;
S[Root2].Parent = S[Root2].Parent - 1;
}
}
}
int main()
{
//读入节点数
int N;
//freopen("test.txt","r",stdin);//debug
scanf("%d",&N);
CreateSetType(N);
//看操作
char operation[10];
int a,b;
while(scanf("%s",operation) == 1)//还有数据输入就循环
{
if(strcmp(operation,"S")==0)break;//结束了,判断有几个集合
if(strcmp(operation,"C")==0)
{
scanf("%d %d",&a,&b);
if((Find(H,a)==Find(H,b)) && (Find(H,a) != -1))//根节点相同说明在一根树上
{
printf("yes\n");
}
else
{
printf("no\n");
}
}
if(strcmp(operation,"I")==0)
{
scanf("%d %d",&a,&b);
Union(H,a,b);
}
}
int num = 0;//统计树的个数
for(int i = 0; i < N; i++)
{
if(H[i].Parent < 0)
{
num++;
}
}
if(num==1)
{
printf("The network is connected.\n");
}
else
{
printf("There are %d components.\n",num);
}
return 0;
}