Establishment of basic query set
Union search set is a data structure that combines disjoint sets. It is often used to find out whether there is a loop in a graph
To build and search a set is to build a tree as balanced as possible. Detect whether there is a loop while establishing
The most important two points:
- Find root node_ root(x)
- Merge two trees union(xTree,yTree)
#include <stdc++.h> using namespace std; #Define validates 6 / / number of nodes int find_root(int x,int parent[]){ int x_root=x; while(parent[x_root]!=-1){ x_root=parent[x_root]; } return x_root; } //return : 1 --success // 0 --fail int union_vertices(int x,int y,int parent[]){ int x_root=find_root(x,parent); int y_root=find_root(y,parent); if(x_root == y_root){ return 0; }else{ parent[x_root]=y_root; return 1; } } int main(){ int parent[VERUTICES]={0}; //Two dimensional array storage edge int edges[5][2]={ {0,1},{1,2},{1,3},{3,4},{2,5} }; memset(parent,-1,sizeof(parent)); //Initialize parent node number group //Traverse 6 edges for(int i=0;i<5;i++){ int x=edges[i][0]; int y=edges[i][1]; if(union_vertices(x,y,parent)==0){ cout<<"Presence loop"<<endl; return 0; } } cout<<"loop-free "<<endl; return 0; }
Compression path
Further compress the path to make it more balanced:
We need to add the following code based on the above code:
1.rank array marks the depth and height of the tree where the root node is located and maintains it (Note: rank [] only needs + 1 when two collection trees are spliced together when the heights are equal)
2. The rank [] value of each node in the following code represents the height of the current node in the tree - 1
#include <stdc++.h> using namespace std; #Define validates 6 / / number of nodes int find_root(int x,int parent[]){ int x_root=x; while(parent[x_root]!=-1){ x_root=parent[x_root]; } return x_root; } //return : 1 --success // 0 --fail int union_vertices(int x,int y,int parent[],int rank[]){ int x_root=find_root(x,parent); int y_root=find_root(y,parent); if(x_root == y_root){ return 0; }else{ if(rank[x_root]>rank[y_root]){ parent[y_root]=x_root; }else if(rank[x_root]<rank[y_root]){ parent[x_root]=y_root; }else{ parent[x_root]=y_root; rank[y_root]++; } return 1; } } int main(){ int parent[VERUTICES]={0}; int rank[VERUTICES]={0}; //Two dimensional array storage edge int edges[5][2]={ {1,2},{3,4},{2,5},{1,3},{0,1} }; memset(parent,-1,sizeof(parent)); //Initialize parent node number group //Traverse 5 edges for(int i=0;i<5;i++){ int x=edges[i][0]; int y=edges[i][1]; if(union_vertices(x,y,parent,rank)==0){ cout<<"Presence loop"<<endl; return 0; } } cout<<"loop-free "<<endl; for(int i=0;i<5;i++){ cout<<i<<": "<<rank[i]<<endl; } return 0; }
ps: Well, the side array of this case is special. You can change the order and get different rank values
Disadvantages of this compression algorithm:
1. The tree is not necessarily balanced, but we make it tend to be balanced.
2. This is the case where multi tree is allowed
Relationship with Kruskal algorithm (minimum spanning tree)
Kruskal algorithm: for a weighted undirected graph with n nodes, row from large to small according to the weight of the edge, and take out one edge and two nodes each time (note that two nodes with different connected components cannot form a ring). Finally, the minimum spanning tree of n-1 edges is generated.
In the kruskar algorithm, we need to merge two different connected components without rings.
In the merge set, we merge two different tree regions without rings.
It can be found that cruzcar's most important merge operation in code implementation is completed by the data structure of merge query set.
For example, figure 1 is the weight of all nodes, which makes all nodes independent. After several edge selection and merging operations, it becomes Figure 2. At this time, the two connected components of merged Figure 2 can be used and searched.