本题依然是并查集的应用,与上一个监狱的问题不同,本题计算的是距离,通过记录通往自己父节点距离的相对距离,与父节点到根节点(代表元素)的距离依次相加
路径压缩时每次都要更新节点。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int maxn=30001; int p; struct { int father,tot,dis; }block[maxn]; void in() { for(int i=0;i<maxn;++i) { block[i].dis=0; block[i].father=i; block[i].tot=1; } } int getanc(int a) { if(block[a].father==a) return a; int ret; ret=getanc(block[a].father); block[a].dis+=block[block[a].father].dis; block[a].father=ret; return ret; } void union_set(int a,int b) { int aa=getanc(a); int bb=getanc(b); block[bb].dis=block[aa].tot;//b元素的代表元素到代表元素的距离 block[bb].father=aa;//b元素的代表元素父节点更新 block[aa].tot+=block[bb].tot;//元素总个数更新 } void print(int a) { int aa=getanc(a); printf("%d\n",block[aa].tot-block[a].dis-1); //代表元素总个数-当前元素到代表元素的距离-本身=其下元素个数 } int main() { scanf("%d",&p); char s; int x,y; in(); while(p--) { getchar(); scanf("%c",&s); if(s=='M') { scanf("%d %d",&x,&y); union_set(x,y); } else {scanf("%d",&x);print(x);} } return 0; }
时间: 2024-11-04 05:35:43