集合运算、并查集、按秩归并、路径压缩

Posted on 2019-12-24 17:10  金色的省略号  阅读(293)  评论(0编辑  收藏  举报

file transfer

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?

  1 #include <stdio.h>
  2 /* 
  3         测试用例1
  4         5
  5         C 3 2
  6         I 3 2
  7         C 1 5
  8         I 4 5
  9         I 2 4
 10         C 3 5
 11         S
 12         测试用例2
 13         5
 14         C 3 2
 15         I 3 2
 16         C 1 5
 17         I 4 5
 18         I 2 4
 19         C 3 5
 20         I 1 3
 21         C 1 5
 22         S
 23  */
 24  
 25 /* 集合的简化 */
 26 #define MaxSize 1000 
 27 typedef int ElementType; /*默认元素可以用非负整数表示*/
 28 typedef int SetName; /*默认用根结点的下标作为集合名称*/
 29 typedef ElementType SetType[MaxSize];/* 定义集合类型 */
 30 
 31 /* Initialization */
 32 void Initialization( SetType S , int n )
 33 {
 34     int i;
 35     for ( i=0; i<n; i++ ) S[i] = -1;
 36 }
 37 
 38 /* find */
 39 SetName Find( SetType S, ElementType X )
 40 { 
 41     if ( S[X] < 0 ) /* 找到集合的根 */
 42         return X;
 43     else    
 44         return S[X] = Find( S, S[X] );
 45         /*  路径压缩:
 46             先找到根,
 47             把根变成 X 的父结点,
 48             再返回根。
 49         */
 50 }
 51 
 52 /* union */
 53 void Union( SetType S, SetName Root1, SetName Root2 )
 54 {     /* 按规模 比元素个数,少的贴多的 */
 55     if ( S[Root2]<S[Root1] ){ //负数,小即多
 56         S[Root2] += S[Root1];
 57         S[Root1] = Root2;
 58     }
 59     else {
 60         S[Root1] += S[Root2];
 61         S[Root2] = Root1;
 62     }
 63     /* 
 64     //按树高 比树高,矮树贴高树
 65     if ( S[Root2] < S[Root1] )
 66         S[Root1] = Root2;
 67     else {
 68         if ( S[Root1]==S[Root2] ) S[Root1]--;
 69         S[Root2] = Root1;
 70     } */
 71 }
 72 
 73 /* input */
 74 void Input_connection( SetType S )
 75 { 
 76     ElementType u, v;
 77     SetName Root1, Root2;
 78     scanf("%d %d\n", &u, &v);
 79     Root1 = Find(S, u-1);
 80     Root2 = Find(S, v-1);
 81     if ( Root1 != Root2 )
 82         Union( S, Root1, Root2 );
 83 }
 84 
 85 /* check connection */
 86 void Check_connection( SetType S )
 87 { 
 88     ElementType u, v;
 89     SetName Root1, Root2;
 90     scanf("%d %d\n", &u, &v);
 91     Root1 = Find(S, u-1);
 92     Root2 = Find(S, v-1);
 93     if ( Root1 == Root2 )
 94         printf("yes\n");
 95     else printf("no\n");
 96 }
 97 
 98 /* check network */
 99 void Check_network( SetType S, int n )
100 { 
101     int i, counter = 0;
102     for (i=0; i<n; i++) {
103         if ( S[i] < 0 ) counter++;
104     }
105     if ( counter == 1 )
106         printf("The network is connected.\n");
107     else
108         printf("There are %d components.\n", counter);
109 }
110 
111 /* 测试 */
112 int main()
113 {   
114     SetType S;
115     int n;
116     char in;
117     scanf("%d\n", &n);
118     Initialization( S, n );
119     do {
120         scanf("%c", &in);
121         switch (in) {
122             case 'I': Input_connection( S ); break;
123             case 'C': Check_connection( S ); break;
124             case 'S': Check_network( S, n ); break;
125         }
126     } while ( in != 'S');
127     return 0;
128 }
集合(树),并查集、按秩归并、路径压缩