Union checking set
And look up the problems solved
- Merge two sets
- Ask if two elements are in a collection
Basic principle
Each set is maintained in the form of a tree. The number of the tree root is the number of the whole set. Each node stores its parent node. p[x] represents the parent node of X
Question 1, how to judge the root of tree: if(p[x] == x);
Question 2, how to find the number of X set: while (P [x]! = x) x = P [x];
Question 3: how to merge two sets? P x is the number of X sets, and p y is the number of Y sets. Let p[x]=y.
Problem 2 Optimization: after a node finds the root node, it points the whole path directly to the root node.
Example
AcWing 836 merge set
There are n numbers in total. The numbers are 1-n. at the beginning, each number is in a set.
Now m operations are needed. There are two types of operations:
- "M a b" merges the sets of two numbers a and b. if the two numbers are already in the same set, this operation is ignored;
- "Q a b", asking whether the two numbers a and b are in the same set;
import java.util.*; class UnionSet{ private final int N = 100010; private int[] p = new int[N]; public UnionSet(){ for(int i = 0; i < N; i++){ p[i] = i; } } // Find the root node of this node public int find(int val){ int temp = val; while(p[temp] != temp){ temp = p[temp]; } p[val] = temp; return temp; } public void union(int a,int b){ int pa = find(a); int pb = find(b); if(pa != pb) p[pa] = pb; } public boolean isunion(int a,int b){ int pa = find(a); int pb = find(b); if(pa != pb) return false; else return true; } } public class Main{ public static void main(String[] args){ Scanner Reader = new Scanner(System.in); int n = Reader.nextInt(); int m = Reader.nextInt(); UnionSet us = new UnionSet(); while(m-- != 0){ String temp = Reader.next(); if(temp.equals("M")){ int v1 = Reader.nextInt(),v2 = Reader.nextInt(); us.union(v1,v2); } if(temp.equals("Q")){ if(us.isunion(Reader.nextInt(),Reader.nextInt())) System.out.println("Yes"); else System.out.println("No"); } } } }
Number of midpoint in AcWing 837 connected block
Given an undirected graph with n points (No. 1~n), there is no edge in the graph at the beginning.
Now, m operations are needed. There are three types of operations:
- "C a b", connecting a side between point a and point b, a and b may be equal;
- "Q1 a b", asking whether point a and point b are in the same connected block, a and b may be equal;
- "Q2 a", the number of the midpoint of the connecting block where query point a is located;
import java.util.*; class UnionSet{ private final int N = 100010; private int[] p = new int[N]; private int[] size = new int[N]; public UnionSet(){ for(int i = 0; i < N; i++){ p[i] = i; size[i] = 1; } } // Find the root node of this node public int find(int val){ int temp = val; while(p[temp] != temp){ temp = p[temp]; } p[val] = temp; return temp; } public void union(int a,int b){ int pa = find(a); int pb = find(b); if(pa != pb) { p[pa] = pb; size[pb] += size[pa]; } } public boolean isunion(int a,int b){ int pa = find(a); int pb = find(b); if(pa != pb) return false; else return true; } public int size(int a){ return size[find(a)]; } } public class Main{ public static void main(String[] args){ Scanner Reader = new Scanner(System.in); int n = Reader.nextInt(); int m = Reader.nextInt(); UnionSet us = new UnionSet(); while(m-- != 0){ String temp = Reader.next(); if(temp.equals("C")){ int v1 = Reader.nextInt(),v2 = Reader.nextInt(); us.union(v1,v2); } if(temp.equals("Q1")){ if(us.isunion(Reader.nextInt(),Reader.nextInt())) System.out.println("Yes"); else System.out.println("No"); } if(temp.equals("Q2")){ System.out.println(us.size(Reader.nextInt())); } } } }