1. 程式人生 > >luogu P1196 銀河英雄傳說

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\n",query(x,y)); 68 } 69 } 70 return 0; 71 }

這裡sze我讓每個節點都返回整個的sze 方便一點