中文大意:
日本总共有 n 颗龙珠,被神龙放置在了 n 个城市中。
T A B :将龙珠 A 所在城市中的所有龙珠运送到龙珠 B 的所在城市。假定这两个城市是不同的。
Q A :输出龙珠 X 所在的城市,该市中龙珠的个数以及龙珠 X 的运输次数。
思路:
一个城市就是一个集合,龙珠就是集合中的节点。
本题的难点在于,如何更新每个龙珠的移动次数。
在合并操作中,times[x]++; 只是更新了原根节点的移动次数。而非根节点的移动次数并未更新。
非根节点的移动次数 = 当前节点的移动次数 + 原根节点的移动次数 + ...
这个过程,需要利用迭代操作来实现,请结合下面例子自行体会:
4
T 1 2
T 2 3
T 3 4
Q 1
代码:
#include<iostream>using namespace std;int n,q;int city[10001];//各龙珠所在城市 int times[10001];//各龙珠的移动次数 int cnt[10001];//各城市的龙珠个数 void init(){for(int i=1;i<=n;i++){ city[i] = i; times[i] = 0; cnt[i] = 1; } }//寻找龙珠 x 的所在城市 int find(int x){if(city[x] == x){return x; }int root = find(city[x]);//当前龙珠的移动次数 = 当前龙珠移动次数 + 根节点龙珠移动次数 times[x] += times[city[x]]; city[x] = root;return root; }//合并 void union_set(int x, int y){ x = find(x); y = find(y); city[x] = y; times[x]++; cnt[y] += cnt[x]; }int main(){int t; scanf("%d", &t);for(int k=1;k<=t;k++){ scanf("%d %d", &n, &q); init(); printf("Case %d:\n",k); char c;int x,y;for(int i=0;i<q;i++){ getchar(); scanf("%c", &c); if(c == 'T'){ scanf("%d %d", &x, &y); union_set(x, y); }else if(c == 'Q'){ scanf("%d", &x);int root = find(x); printf("%d %d %d\n", root, cnt[root], times[x]); } } } }