P196 银河英雄传说
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> typedef long long ll; #define rep(i, a, b) for(int i = a; i <= b; ++i) #define per(i, a, b) for(int i = a; i >= b; --i) #define vec(i) for (int i = head[x]; i; i = nxt[i]) #define clr(a,b) memset((a),b,sizeof(a)) using namespace std; const int N = 1e5 + 20; const int M = 505; inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); } return s * w; } int t, fa[N], siz[N], sum[N]; //siz[i]:i所在的链的规模 //sum[i]:i到其所在根节点的距离 int find(int x) { if(x == fa[x]) return x; else { int t = fa[x]; //先记录下fa fa[x] = find(fa[x]); // 当返回时,fa[x]已经改变,即当此句执行完后 fa[x] != t siz[x] = siz[t]; sum[x] += sum[t]; // 合并父亲的权值 } return fa[x]; } //带权并查集实际上就类似于前缀和,通过已知的两个相对信息求出一个绝对信息 int main() { t = read(); rep(i, 1, 30000) fa[i] = i, siz[i] = 1; while(t --) { char c = getchar(); while(c != 'M' && c != 'C') c = getchar(); if(c == 'M') { int x = read(), y = read(); int a = find(x), b = find(y); if(a == b) continue; fa[a] = b; //将以a为首的链 连到b为首的链 sum[a] = siz[b]; //a到跟节点(b)的距离 = b的规模 siz[b] += siz[a]; //b 所在的规模 加入了a的规模 siz[a] = siz[b]; } if(c == 'C') { int x = read(), y = read(); int a = find(x), b = find(y); if(a != b) printf("-1\n"); else printf("%d\n", abs(sum[x] - sum[y]) - 1); } } return 0; }