• + 0 comments

    Typescript union find with path compression, rank comparison and size tracking:

    class UnionFind {
        par: {[key: number]: number} = {}
        rank: {[key: number]: number} = {}
        size: {[key: number]: number} = {}
        
        constructor(n: number) {
            for(let i = 1; i <= n; i++) this.par[i] = i, this.rank[i] = 1, this.size[i] = 1
        }
        
        getSize(x: number): number {
            const p = this.find(x)
            return this.size[p]
        }
        
        find(x: number): number {
           if (this.par[x] === x) {
               return x
           } else {
               this.par[x] = this.find(this.par[x])
               return this.par[x]
           }
        }
        
        union(n1: number, n2: number) {
            let p1 = this.find(n1), p2 = this.find(n2)
            if (p1 == p2) return true
            if (this.rank[p1] < this.rank[p2]) {
                this.par[p1] = p2
                this.size[p2] += this.size[p1]
            } else if (this.rank[p1] > this.rank[p2]) {
                this.par[p2] = p1
                this.size[p1] += this.size[p2]
            } else {
                this.par[p1] = p2
                this.rank[p2]++
                this.size[p2] += this.size[p1]
            }
        }
        
        print() {
            console.log('------')
            console.log('par', this.par)
            console.log('rank', this.rank)
            console.log('size', this.size)
        }
    }
    
    function main() {
        const [n, q] = readLine().split(' ').map(e => parseInt(e))
        const uf = new UnionFind(n)
        for (let k = 0; k < q; k++) {
            const [c, i, j] = readLine().split(' ')
            if (c === 'M') {
                uf.union(parseInt(i), parseInt(j))
            } else if (c === 'Q') {
                console.log(uf.getSize(parseInt(i)))
            }
        }
    }