凛冬之翼---路径压缩和按秩归并

感觉写代码在慢慢上路了,加油少年!
题目:
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.

解题思路:1.这道题主要核心就是考察路径压缩和按秩归并是属于树类型的题目
路径压缩:
路径压缩思路图
代码:

`int Find(int S[],int x)   //to find the father of x
{
	if(S[x]<0) return x;       //PAth compression
	else return S[x]=Find(S,S[x]);
}`

按秩归并:
按秩归并思路图

void Union(int S[],int Root1,int Root2){   //let two gather have the same root
	if(S[Root2]<S[Root1]) S[Root1]=Root2;   //S[Root2]<S[Root1]means the height of Root2 is bigger than Root1 than let Root1 into Root2
	else { if(S[Root1]==S[Root2]) S[Root1]--;
	S[Root2]=Root1;
	}
}

遇到的问题:在写for( ;S[x]>=0;x=S[x]);类似的代码的时候记得在后面加上;号。不然运行会出错。

下面是TSSN版本的代码:

#include<stdio.h>
#include<stdlib.h>

#define Max 10001


int Find(int S[],int x);
void Initialization(int S[],int n);
void Union(int S[],int Root1,int Root2);
void Input_connection(int S[]);
void Check_connection(int S[]);
void Check_network(int S[]);



int Find(int S[],int x)   //to find the father of x
{
	for( ;S[x]>=0;x=S[x]);
	return x;
}

void Initialization(int S[],int n){
	for(int i=0;i<n;i++)
	S[i]=-1;
}

void Union(int S[],int Root1,int Root2){   //let two gather have the same root
	S[Root1]=Root2;
}

void Input_connection(int S[]){      //if the fathers of two items aren't the same than let they the same
	int n,m;
	int Root1,Root2;
	scanf("%d %d",&n,&m);
	Root1=Find(S,n-1);
	Root2=Find(S,m-1);
	if(Root1!=Root2){
	S[Root1]=Root2;
	}	
}

void Check_connection(int S[]){      // using roots to check wether the two items are the same 
	int n,m;
	int Root1,Root2;
	scanf("%d %d",&n,&m);
	Root1=Find(S,n-1);
	Root2=Find(S,m-1);
	if(Root1!=Root2)  printf("no\n");
	else printf("yes\n");
}

void Check_network(int S[],int n){     //if the only one item's father is negetive means the items is built
	int check=0;
	for(int i=0;i<n;i++){
		if(S[i]<0) check=check+1;
	}
	if(check==1) printf("The network is connected.");
	else printf("There are %d components.\n",check);
}



int main(){
	int n;
	char in;
	int S[Max];
	scanf("%d",&n);
	Initialization(S,n);
	do{
		scanf("%c",&in);
		switch(in){
			case'I':Input_connection(S);break;
			case'C':Check_connection(S);break;
			case'S':Check_network(S,n);break;
		}
	}while(in!='S');
//	for(int i=0;i<n;i++){
//		printf("%d ",S[i]);
//	}
	return 0;
}

下面是mature版本的代码:

#include<stdio.h>
#include<stdlib.h>

#define Max 10001


int Find(int S[],int x);
void Initialization(int S[],int n);
void Union(int S[],int Root1,int Root2);
void Input_connection(int S[]);
void Check_connection(int S[]);
void Check_network(int S[]);



int Find(int S[],int x)   //to find the father of x
{
	if(S[x]<0) return x;       //PAth compression
	else return S[x]=Find(S,S[x]);
}

void Initialization(int S[],int n){
	for(int i=0;i<n;i++)
	S[i]=-1;
}

void Union(int S[],int Root1,int Root2){   //let two gather have the same root
	if(S[Root2]<S[Root1]) S[Root1]=Root2;   //S[Root2]<S[Root1]means the height of Root2 is bigger than Root1 than let Root1 into Root2
	else { if(S[Root1]==S[Root2]) S[Root1]--;
	S[Root2]=Root1;
	}
}

void Input_connection(int S[]){      //if the fathers of two items aren't the same than let they the same
	int n,m;
	int Root1,Root2;
	scanf("%d %d",&n,&m);
	Root1=Find(S,n-1);
	Root2=Find(S,m-1);
	Union(S,Root1,Root2);	
}

void Check_connection(int S[]){      // using roots to check wether the two items are the same 
	int n,m;
	int Root1,Root2;
	scanf("%d %d",&n,&m);
	Root1=Find(S,n-1);
	Root2=Find(S,m-1);
	if(Root1!=Root2)  printf("no\n");
	else printf("yes\n");
}

void Check_network(int S[],int n){     //if the only one item's father is negetive means the items is built
	int check=0;
	for(int i=0;i<n;i++){
		if(S[i]<0) check=check+1;
	}
	if(check==1) printf("The network is connected.");
	else printf("There are %d components.\n",check);
}



int main(){
	int n;
	char in;
	int S[Max];
	scanf("%d",&n);
	Initialization(S,n);
	do{
		scanf("%c",&in);
		switch(in){
			case'I':Input_connection(S);break;
			case'C':Check_connection(S);break;
			case'S':Check_network(S,n);break;
		}
	}while(in!='S');
//	for(int i=0;i<n;i++){
//		printf("%d ",S[i]);
//	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39042981/article/details/83859539