数据结构习题集-4-2 集合的运用
1.题目:
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.
2.题目分析:
其实这个题目感觉比4-1要更简单一些,AVL二叉树反而自己更难一些。
我使用一个结构来来描述每一个节点,因为输入的节点就是X,所以我觉得没有必要在这个结构中定义data。直接用输入的X-1指向数组中的节点就可以了。
每一个结构中定义一个parent,指向父节点的index。
查找父节点就变得很简单了,直接从A[x-1],跟链表遍历一样一直追溯到parent < 0为止。(我们约定如果parent<0,则说明这个节点是父节点)
插入则更简单,查找两个节点的父节点,如果相同,退出,如果不同,则说明父节点不同。将一个节点的父节点指向另一个节点的父节点即可。
最后,遍历所有的节点,统计有多少节点的父节点是小于0的,统计节点个数。
按规定输出。
不过,很莫名的发现了有一个测试条件超时。突然觉得按照set的元素数字大小比对后进行union后才可以。
所以在合并的时候,比较parent值得大小,如果将parent的绝对值比较大的那一个作为父节点,将小parent加入父parent,累积元素个数。
然后非常完美的通过了。
源代码如下:
1 #include <stdio.h> 2 3 int MaximumSize; 4 5 typedef struct setNode{ 6 // int data; 7 int parent; 8 }tSet; 9 10 int FindSet(tSet a[] , int x) 11 { 12 // i is the index of x; 13 int i = x - 1; 14 if(x > MaximumSize) 15 { 16 return -1; 17 } 18 for(;(a[i].parent)>=0;i=a[i].parent) 19 { 20 if(i>=MaximumSize) 21 return -1; 22 } 23 return i; 24 } 25 26 int UnionSet(tSet a[], int x, int y) 27 { 28 int px = FindSet(a,x); 29 int py = FindSet(a,y); 30 if(px==-1 || py ==-1) 31 { 32 return -1; 33 }//if any of the xy is not in the set; 34 if(px!=py) 35 { 36 if(a[px].parent < a[py].parent) 37 { 38 a[px].parent = a[px].parent + a[py].parent; 39 a[py].parent = px; 40 } 41 else 42 { 43 a[py].parent = a[px].parent + a[py].parent; 44 a[px].parent = py; 45 } 46 // a[px].parent = py; 47 } 48 return 0; 49 } 50 51 int SetNum(tSet a[]) 52 { 53 int count = 0; 54 int i = 0; 55 for(;i<MaximumSize;i++) 56 { 57 if(a[i].parent < 0) 58 { 59 count++; 60 } 61 } 62 return count; 63 } 64 65 //tSet* SetInitial() 66 //{ 67 // tSet *a = malloc(sizeof(tSet)*MaximumSize); 68 // int i=0; 69 // for(;i<MaximumSize;i++) 70 // { 71 // a[i].parent = -1; 72 // } 73 // return a; 74 //} 75 76 int main() 77 { 78 79 int x; 80 int y; 81 char ch; 82 int count; 83 int i = 0; 84 scanf("%d",&MaximumSize); 85 tSet a[MaximumSize]; 86 for(;i<MaximumSize;i++) 87 { 88 a[i].parent = -1; 89 } 90 91 92 while(1) 93 { 94 95 scanf("%c",&ch); 96 if(ch=='C') 97 { 98 scanf("%d %d",&x,&y); 99 if((FindSet(a,x)==FindSet(a,y))&&(FindSet(a,x)>=0)) 100 { 101 printf("yes\n"); 102 } 103 else 104 { 105 printf("no\n"); 106 } 107 } 108 else if(ch == 'I') 109 { 110 scanf("%d %d",&x,&y); 111 UnionSet(a,x,y); 112 } 113 else if(ch == 'S') 114 { 115 break; 116 } 117 } 118 count = SetNum(a); 119 if(count > 1) 120 { 121 printf("There are %d components.\n",count); 122 } 123 else 124 { 125 printf("The network is connected."); 126 } 127 }