[Javascript] Union Find easy and concise
Intuition:\n\tUnion find appeals to problems related to paths that traverse the whole tree. Here we create two union finds, one for each player. The important t
**Intuition**:\n\tUnion find appeals to problems related to paths that traverse the whole tree. Here we create two union finds, one for each player. The important thing here is to always prefer type 3 edges over 2 or 1 because the latter are reduntant once the type 3 is chosen. So the whole idea is filling up my unionfinds with the components while keeping track of the edges I\'m using. In the end, the number of groups in each unionfind has to be 1 for each, meaning that both players can traverse the whole tree. If not, then the tree is not traversable and -1 has to be returned.  The result is the total available edges minus the ones I actually used.\n\t\n```\nclass UnionFind {\n\n    // Construction takes O(n)\n    constructor(size){\n        //the total count of different elements(not groups) in this union find\n        this.count=size\n        //tracks the sizes of each of the components(groups/sets)\n        //groupsize[a] returns how many elements the component with root a has \n        this.groupSize=[...Array(size)] \n        //number of components(groups) in the union find\n        this.numComponents=size\n        //points to the parent of i, if parent[i]=i, i is a root node\n        this.parent=[...Array(size)]  //which is also the index of the group\n\n        //put every element into its own group\n        // rooted at itself\n        for (let i = 0; i < size; i++) {\n            this.groupSize[i]=i     \n            this.parent[i]=i            \n        }\n    }\n\n\n\n    //returns to which component (group) my element belongs to \n    // \u03B1(n) --Amortized constant time \n    // Update: Also compresses the paths so that each child points to its \n    // parent\n    find(element){\n        let root=element\n        //find the parent of the group the elemnt belongs to\n        // When root===parent[root] is always the parent of that group (root)\n        while(root!=this.parent[root])\n            root=this.parent[root]\n\n        // Compression, point the element to its parent if its not already pointed\n        // Tldr: Not only do I point my element to its actual root, i point any\n        // inbetween elements to that root aswell\n        while(element!=root){\n            let next=this.parent[element]\n            this.parent[element]=root\n            element=next\n        }\n        \n        return root\n    }   \n\n    //Unifies the sets containing A and B\n    // \u03B1(n) --Amortized constant time \n    union(A,B){\n        let root1=this.find(A) //parent of A\n            ,root2=this.find(B) //parent of B\n\n        // I want to put the set with fewer elements \n        // to the one with more elemenets\n        if(this.groupSize[root1]<this.groupSize[root2]){\n            this.groupSize[root2]+=this.groupSize[root1]\n            this.parent[root1]=this.parent[root2]\n        }\n        else {\n            this.groupSize[root1]+=this.groupSize[root2]\n            this.parent[root2]=this.parent[root1]\n        }\n\n        this.numComponents-- //cos 1 less group, since i merged 2\n    }\n\n    //same parent=>samegroup\n    sameGroup=(A,B)=>this.find(A)==this.find(B)\n\n    //essentially the groupSize of its parent\'s group\n    sizeOfGroup=(A)=>this.groupSize[this.find(A)]\n\n}\n\n//Main Function\n var maxNumEdgesToRemove = function(n, edges) {\n    edges.sort((a,b)=>b[0]-a[0]) //sort to always prefer type 3 first\n    let edgesUsed=0,Bob=new UnionFind(n),Alice=new UnionFind(n)\n    \n    for (const [type,f,to] of edges) {\n        if((type==3||type==2)&&!Bob.sameGroup(f,to)){\n            Bob.union(f,to)\n            edgesUsed++\n        }\n        if((type==3||type==1)&&!Alice.sameGroup(f,to)){\n            Alice.union(f,to)\n            if(type==1)// I already incremented above for type 3s\n\t\t\t\tedgesUsed++\n        }\n    }\n\t\n\t//can they both traverse the whole tree?\n    if(Bob.numComponents!=1||Alice.numComponents!==1)\n        return -1\n    return edges.length-edgesUsed\n };\n\n\t\n```
['Union Find', 'JavaScript']