题意:
若干个个方块,2种操作:
M 将u所在的方块堆整体移动到v所在的方块堆;
C 询问u方块下面有多少块方块。
做法:带权并查集
1) 对于每个根节点,拥有属性SetSize【root】 , 即此集合的大小;
2)对于每个节点,拥有属性distanceToRoot【u】 ,即此节点 距离所在集合 根节点的距离, 根节点离自己距离为0
3)在压缩路径,递归操作时,维护的是distanceToRoot 值;
4)在合并操作时, 维护的是SetSize【fromRoot】 与 distanceToRoot【toRoot】
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) {
new POJ1988().solve();
}
}
class POJ1988 {
InputReader in = new InputReader(System.in);
PrintWriter out = new PrintWriter(System.out);
final int N = 30008 ;
int[] father = new int[N] ;
int[] distanceToRoot = new int[N] ;
int[] setSize = new int[N] ;
void init(){
for(int i = 1 ; i < N ; i++){
father[i] = i ;
setSize[i] = 1 ;
distanceToRoot[i] = 0 ;
}
}
int getRoot(int u){
if(u == father[u]) return u ;
int root = getRoot(father[u]) ;
distanceToRoot[u] += distanceToRoot[father[u]] ;
return father[u] = root ;
}
void move(int from , int to){
int rootFrom = getRoot(from) ;
int rootTo = getRoot(to) ;
if(rootFrom != rootTo){
father[rootTo] = rootFrom ;
distanceToRoot[rootTo] += setSize[rootFrom] ;
setSize[rootFrom] += setSize[rootTo] ;
}
}
void solve() {
init() ;
int n = in.nextInt() ;
while(n-- > 0){
if("C".equals(in.next())){
int u = in.nextInt() ;
int root = getRoot(u) ;
out.println(setSize[root] - distanceToRoot[u] - 1) ;
}
else{
move(in.nextInt() , in.nextInt()) ;
}
}
out.flush() ;
}
}
class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = new StringTokenizer("");
}
private void eat(String s) {
tokenizer = new StringTokenizer(s);
}
public String nextLine() {
try {
return reader.readLine();
} catch (Exception e) {
return null;
}
}
public boolean hasNext() {
while (!tokenizer.hasMoreTokens()) {
String s = nextLine();
if (s == null)
return false;
eat(s);
}
return true;
}
public String next() {
hasNext();
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}