1. 程式人生 > >凜冬之翼---路徑壓縮和按秩歸併

凜冬之翼---路徑壓縮和按秩歸併

感覺寫程式碼在慢慢上路了,加油少年!
題目:
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;
}