每个结点除了维护父亲结点编号以外,多维护一个sum值和r值,表示该子树的总结点数(如果该结点是根则sum值有效)以及它到根的距离(即被运输了几次),然后在路径压缩和集合合并的时候顺便维护这两个值即可。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 10001; 7 int f[N]; 8 int sum[N]; 9 int r[N]; 10 11 void init( int n ) 12 { 13 for ( int i = 1; i <= n; i++ ) 14 { 15 f[i] = i; 16 sum[i] = 1; 17 r[i] = 0; 18 } 19 } 20 21 int findf( int x ) 22 { 23 if ( f[x] == x ) return x; 24 int tx = findf(f[x]); 25 r[x] = r[x] + r[f[x]]; 26 f[x] = tx; 27 return f[x]; 28 } 29 30 void union_set( int x, int y ) 31 { 32 x = findf(x), y = findf(y); 33 if ( x == y ) return ; 34 f[x] = y; 35 sum[y] += sum[x]; 36 r[x]++; 37 } 38 39 int main () 40 { 41 int t; 42 scanf("%d", &t); 43 for ( int _case = 1; _case <= t; _case++ ) 44 { 45 printf("Case %d:\n", _case); 46 int n, m; 47 scanf("%d%d", &n, &m); 48 init(n); 49 while ( m-- ) 50 { 51 char op[2]; 52 int x, y; 53 scanf("%s", op); 54 if ( op[0] == ‘T‘ ) 55 { 56 scanf("%d%d", &x, &y); 57 union_set( x, y ); 58 } 59 else 60 { 61 scanf("%d", &x); 62 int ans1 = findf(x); 63 int ans2 = sum[ans1]; 64 int ans3 = r[x]; 65 printf("%d %d %d\n", ans1, ans2, ans3); 66 } 67 } 68 } 69 return 0; 70 }
时间: 2024-10-22 22:13:29