又是基于连通性的问题,可以用并查集来解决,每个集合都维护一个优先队列,合并的时候按照优先队列的大小启发式合并即可。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 7 const int N = 100001; 8 int f[N]; 9 priority_queue<int> q[N]; 10 int n, m; 11 12 void init() 13 { 14 for ( int i = 1; i <= n; i++ ) 15 { 16 f[i] = i; 17 while ( !q[i].empty() ) q[i].pop(); 18 } 19 } 20 21 int findf( int x ) 22 { 23 if ( f[x] != x ) f[x] = findf( f[x] ); 24 return f[x]; 25 } 26 27 int union_set( int x, int y ) 28 { 29 x = findf(x), y = findf(y); 30 if ( x == y ) return -1; 31 int sx = q[x].top(); 32 q[x].pop(); 33 sx >>= 1; 34 int sy = q[y].top(); 35 q[y].pop(); 36 sy >>= 1; 37 if ( q[x].size() > q[y].size() ) swap( x, y ); 38 f[x] = y; 39 while ( !q[x].empty() ) 40 { 41 int nn = q[x].top(); 42 q[x].pop(); 43 q[y].push(nn); 44 } 45 q[y].push(sx); 46 q[y].push(sy); 47 return q[y].top(); 48 } 49 50 int main () 51 { 52 while ( scanf("%d", &n) != EOF ) 53 { 54 init(); 55 for ( int i = 1; i <= n; i++ ) 56 { 57 int tmp; 58 scanf("%d", &tmp); 59 q[i].push(tmp); 60 } 61 scanf("%d", &m); 62 while ( m-- ) 63 { 64 int u, v; 65 scanf("%d%d", &u, &v); 66 printf("%d\n", union_set( u, v )); 67 } 68 } 69 return 0; 70 }
时间: 2024-10-26 02:40:57