1. 程式人生 > >【NOIP2002】銀河英雄傳說

【NOIP2002】銀河英雄傳說

本題在洛谷上的連結:https://www.luogu.org/problemnew/show/P1196


 

又是一道帶權並查集的題,沒太多難度,就是吧。。。

為了提高程式碼能力,換了一種更鬆散的程式碼風格,導致之前的讀入優化有一行很長,所以就去抄了某位大佬的模板,結果被帶跑了。。。

讀入字元時傻了一樣“跳”著讀,結果全TLE了。。。

說正事,顯然我們需要維護每個結點到其祖先的距離,而這個距離恰好是該結點之前的結點個數,因此我們還需要維護每個並查集的結點個數,注意,只需要維護祖先的就可以,其他結點可以找到祖先,然後查詢祖先的即可。

然後就是查詢時要加絕對值,然後還要減1,這題坑基本沒有,還算友好。

 1 #include <cstdio>
 2 #include <cmath>
 3 
 4 inline int get_num() {
 5     int num = 0;
 6     char c = getchar();
 7     while (c < '0' || c > '9') c = getchar();
 8     while (c >= '0' && c <= '9')
 9         num = num * 10 + c - '0', c = getchar();
10 return num; 11 } 12 13 const int maxn = 3e4 + 5; 14 15 int fa[maxn], dist[maxn], size[maxn]; 16 17 int dj_find(int i) { 18 if (i == fa[i]) return i; 19 int old = fa[i]; 20 fa[i] = dj_find(old); 21 dist[i] += dist[old]; 22 return fa[i]; 23 } 24 25 inline void
dj_merge(int a, int b) { 26 a = dj_find(a), b = dj_find(b); 27 if (a != b) { 28 fa[a] = b; 29 dist[a] += size[b]; 30 size[b] += size[a]; 31 } 32 } 33 34 int main() { 35 for (int i = 1; i <= 30000; ++i) 36 fa[i] = i, dist[i] = 0, size[i] = 1; 37 int t, a, b; 38 char c; 39 t = get_num(); 40 for (int i = 1; i <= t; ++i) { 41 c = 0; //此處史無前例的坑! 42 while (c != 'M' && c != 'C') 43 c = getchar(); 44 a = get_num(), b = get_num(); 45 if (c == 'M') dj_merge(a, b); 46 else { 47 if (dj_find(a) != dj_find(b)) printf("-1\n"); 48 else printf("%d\n", abs(dist[a] - dist[b]) - 1); 49 } 50 } 51 return 0; 52 }
AC程式碼