Find them, Catch them

    技术2022-05-12  0

    http://162.105.81.212/JudgeOnline/problem?id=1703

    并查集,用深度差区别是否在一个集合,差为偶,同在一个集合,为奇则相反。

    如果A和B在不同的集合且深度差为偶,直接把A的根指向B的根(B的根指向A的根也可以);

    为奇时,把深度小的根插入深度大的根的子节点;

    TLE了一次,没有进行路径压缩,WA了一次,改的时候,当深度差为奇时,应该指向根的子节点,而不是根节点。

    #include <iostream> #define MAXN 100010 using namespace std ; int set[MAXN] ; int Find (int x , int &h , int &pre) { while (x != set[x]) { pre = x ; x = set[x] ; h ++ ; } return x ; } void Merge (int a , int b) { int x , y , h1 , h2 , pre1 , pre2 ; h1 = h2 = 0 ; x = Find (a , h1 , pre1) ; y = Find (b , h2 , pre2) ; if (x != y) { if ((h1 - h2) % 2 == 0)//差为奇 set[x] = y ; else { if (h1 > h2) set[y] = pre1 ; else set[x] = pre2 ; } } } void Rank (int a , int x , int h , int pre) { int tmp ; while (h) { tmp = set[a] ; if (h & 1) set[a] = x ; else set[a] = pre ; a = tmp ; h -- ; } } int main () { int i , t , n , m , a , b , h1 , h2 , x , y , pre ; char cmd[4] ; scanf ("%d" , &t) ; while (t --) { scanf ("%d%d" , &n , &m) ; for (i = 1 ; i <= n ; i ++) set[i] = i ; while (m --) { scanf ("%s%d%d" , &cmd , &a , &b) ; if (cmd[0] == 'D') Merge (a , b) ; else { h1 = 0 , x = Find (a , h1 , pre) ; Rank (a , x , h1 , pre) ;//路径压缩 h2 = 0 , y = Find (b , h2 , pre) ; Rank (b , y , h2 , pre) ; if (x != y) printf ("Not sure yet./n") ; else if ((h1 - h2) & 1) printf ("In different gangs./n") ; else printf ("In the same gang./n") ; } } } return 0 ; }


    最新回复(0)