本实验源于浙江大学《数据结构》。这道题目在小白专场老师用了多种方法将find和union不断做优化,告诉我们,如果卡查找的话,java必挂。同样的给了我们很多启示,一个程序从简单的去实现它,不断将它进行优化优化,最后优化成最好的是需要过程的。因此我从来不相信一个人天生就是所谓的计算机的大牛,都是一些后天的汗水铸就的,还是来看这道题目吧!
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≤10
4
), 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.
如果再从小白身份去讲解这道题目,没有任何花头了。先搞清楚这个程序干了什么?并查集典型应用!
然后嘞?
一个程序包括输入处理输出。这道题就是一个查连接,另一个是并连接,最后就是返回有几个联通集。所以哈。程序主要函数如下
所以main函数里先将程序输入做好后,根据S I C不断做出查找并集的操作就好了
其中查找方法根据小白专场里,将程序写的极短的函数拿过来。
归并函数用安秩归并的方法再判断树高。
#include
#include
int N;
int Find(int* S,int X)
{
if(S[X]<0) return X;
else return S[X]=Find(S,S[X]);//路径压缩,通过不断地压缩路径,让树越来越扁 */
}
void Union(int* S,int X1,int X2)
{
int root1=Find(S,X1-1);
int root2=Find(S,X2-1);
if(root1==root2)
{
S[root2]=root1;
root1-=root2;
}
else
{
//按秩归并
if(root1<root2)//root1 is bigger than root2,so we Union root2 to root1
{
S[root2]=root1;
root1-=root2;//update the value of root2
}
else
{
S[root1]=root2;
root2-=root1;
}
}
}
void Input_connection(int* S)
{
int x1,x2;
scanf("%d %d",&x1,&x2);
Union(S,x1,x2);
}
void Check_connection(int* S)
{
int x1,x2;
scanf("%d %d",&x1,&x2);
int root1,root2;
root1=Find(S,x1-1);
root2=Find(S,x2-1);
if(root1==root2)
printf("yes\n");
else
printf("no\n");
}
void Check_network(int* S,int N)
{
int flag=0;
for(int i=0;i<N;i++)
{
if(S[i]<0)
flag++;
}
if(flag==1)
printf("The network is connected.");
else
printf("There are %d components.\n",flag);
}
int main()
{
scanf("%d",&N);
int S[N];
for(int i=0;i<N;i++)
S[i]=-1;
char c;
do
{
scanf("%c",&c);
switch(c)
{
case 'C': Check_connection(S);break;
case 'S': Check_network(S,N);break;
case 'I': Input_connection(S);break;
}
}while(c !='S');
return 0;
}