luogu P1196 银河英雄传说

传送门

经典并查集

看的时候思路还卡了一下

这题唯一的问题就在于需要维护一排中最后一个的位置

其实维护一下总个数就行了

sze记录总个数 dis记录与根节点的距离

所以合并方程比较显然

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define By prophetB 
 6 #define rep(i,a,n) for(int i = a;i <= n;i++)
 7 #define per(i,n,a) for(int i = n;i >= a;i--)
 8 #define inf 2147483647
 9 #define ms(a,b) memset(a,b,sizeof a)
10 using namespace std;
11 typedef long long ll;
12 ll read() {
13     ll as = 0,fu = 1;
14     char c = getchar();
15     while(c < '0' || c > '9') {
16         if(c == '-') fu = -1;
17         c = getchar();
18     }
19     while(c >= '0' && c <= '9') {
20         as = as * 10 + c - '0';
21         c = getchar();
22     }
23     return as * fu;
24 }
25 const int N = 30005;
26 //head
27 int pa[N],sze[N],dis[N];
28 int gpa(int x) {
29     if(pa[x] == x) return x;
30     int t = pa[x];
31     pa[x] = gpa(t);
32     sze[x] = sze[pa[x]];
33     dis[x] += dis[t];
34     return pa[x];
35 }
36 
37 void Merge(int x,int y) {
38     int fx = gpa(x);
39     int fy = gpa(y);
40     if(fx == fy) return;
41     pa[fx] = fy;
42     dis[fx] = dis[fy] + sze[fy];
43     sze[fx] = sze[fy] = (sze[fx] + sze[fy]);
44     return;
45 }
46 
47 int query(int x,int y) {
48     int fx = gpa(x);
49     int fy = gpa(y);
50     if(fx == fy) return abs(dis[y] - dis[x]) - 1;
51     else return -1;
52 }
53 
54 int main() {
55     rep(i,1,30000) pa[i] = i,sze[i] = 1;
56     int T = read();
57     char s[5];
58     while(T--) {
59         scanf("%s",s);
60         if(s[0] == 'M') {
61             int x = read();
62             int y = read();
63             Merge(x,y);
64         } else {
65             int x = read();
66             int y = read();
67             printf("%d
",query(x,y));
68         }
69     }
70     return 0;
71 }

这里sze我让每个节点都返回整个的sze 方便一点

> 别忘了 总有人在等着你
原文地址:https://www.cnblogs.com/yuyanjiaB/p/9930859.html