题意:n个城市有n个龙珠,T a,b 代表将龙珠a移动到b城市,Q a代表查询龙珠a所在城市,该城市有多少颗龙珠,该龙珠移动了多少次。
注意:移动时是将龙珠所在该城市所有龙珠都移动,每个龙珠不会再回到自己以前呆过的城市。就是说假如龙珠1,2,3,都在城市2,那么龙珠就不能再移动了
在路径压缩的时候更新他的距离值
rootxx --> rootx 移动是3,rootx -->x的移动是5 那么 rootxx --> x的移动就是rootxx --> rootx+rootx -->x = 3 + 5 = 8
所以还是向量
在find操作的时候
int temp = p[x].father; p[x].father = Find_set(p[x].father); p[x].trap += p[temp].trap;
先保存他以前父亲的节点,然后更新时将他自己的节点和他原父亲的节点运输次数相加。
这样一层一层更新就可以了
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct bian { int sum; int father; int trap; }p[10005]; void Make_set(int n) { int i; for(i = 1; i <= n; i++) { p[i].sum = 1; p[i].father = i; p[i].trap = 0; } } int Find_set(int x) { if(x != p[x].father) { int temp = p[x].father; p[x].father = Find_set(p[x].father); p[x].trap += p[temp].trap; } return p[x].father; } void Union(int a,int b) { int x = Find_set(a); int y = Find_set(b); if(x == y) return ; else { p[x].father = y; p[x].trap++; p[y].sum += p[x].sum; } } int main() { int t,cas = 1; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); int i; Make_set(n);printf("Case %d: ",cas++); for(i = 0; i < m; i++) { char c[5]; int a,b; scanf("%s",c); if(c[0] == 'T') { scanf("%d%d",&a,&b); Union(a,b); } else { scanf("%d",&a); int temp = Find_set(a); printf("%d %d %d ",temp,p[temp].sum,p[a].trap); } } } return 0; }