poj 1988 Cube Stacking
初始有n堆东西每堆一个物品,有两个操作,第一个把含有第x个物品的那堆物品放到含有第y个物品的那堆物品上。
第二个询问第x个物品下面有多少物品。
用并查集维护一个联通块的size以及每个节点到根节点的距离。
第一个操作的时候size[root[x]]+=size[root[y]]并且y的根节点的距离更新为x的联通块的大小。
那么查询的时候把整条路径上的距离更新,并且压缩路径。
最后的答案即为询问点在的联通块大小减去点到根的距离-1。
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int M = 3e4+7; int n; char op[2]; int f[M],sz[M],dis[M]; void init(int n){ for(int i=1;i<=n;i++) f[i]=i,sz[i]=1,dis[i]=0; } int find(int x){ if(f[x]==x) return x; int tmp=f[x]; f[x]=find(f[x]); dis[x]+=dis[tmp]; return f[x]; } int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); scanf("%d",&n); init(30001); while(n--){ scanf("%s",op); if(op[0]=='M'){ int x,y; scanf("%d%d",&x,&y); int fx=find(x),fy=find(y); if(fx!=fy){ dis[fy]=sz[fx]; sz[fx]+=sz[fy]; f[fy]=fx; } } else{ int x; scanf("%d",&x); printf("%d\n",sz[find(x)]-dis[x]-1); } } return 0; }