【带权并查集】银河英雄传说
洛谷P1196 [NOI2002]银河英雄传说
一道喜闻乐见的带权并查集qwq
出了以下锅
- 没在主程序中写上预处理//撞墙吧
- int k = f[x] dis[x] += dis[k]
- 写成 dis[x] += dis[f[x]]
- 意识到f[x]在变以后把这一句写到了f[x] = find(f[x]) 前面QAQ
- 可是这个dis[x] 是由x的祖先一步步推回来的啊QAQ
贴代码QAQ
1 #include<cmath> 2 #include<cstdio> 3 #include<iostream> 4 using namespace std; 5 const int sz = 30030; 6 int f[sz], num[sz], dis[sz]; 7 int T, ans = 0; 8 char opt[2]; 9 void init() { 10 for(int i = 1; i <= 30000; i++) { 11 f[i] = i; 12 num[i] = 1; 13 dis[i] = 0; 14 } 15 } 16 int find(int x) { 17 if(x != f[x]) { 18 int k = f[x]; 19 f[x] = find(f[x]); 20 dis[x] += dis[k]; 21 num[x] = num[f[x]]; 22 } 23 return f[x]; 24 } 25 int merge(int u, int v) { 26 int r1 = find(u), r2 = find(v); 27 f[r1] = r2; 28 dis[r1] = dis[r2] + num[r2]; 29 num[r2] += num[r1]; 30 num[r1] = num[r2]; 31 } 32 int main() { 33 // freopen("qaq.out","w",stdout); 34 scanf("%d",&T); 35 init(); 36 while(T--) { 37 int i, j; 38 scanf("%s",opt+1); 39 if(opt[1]=='M') { 40 scanf("%d%d",&i, &j); 41 merge(i, j); 42 } 43 else { 44 scanf("%d%d",&i, &j); 45 if(find(i) != find(j)) { 46 printf("-1\n"); 47 continue; 48 } 49 else { 50 ans = abs(dis[i] - dis[j]) - 1; 51 printf("%d\n",ans); 52 } 53 } 54 } 55 return 0; 56 }
总之岁月漫长,然而值得期待。