Union-Find Algorithm and Path Compression


[Switch] Union search algorithm and path compression

And checking the set is a trick I learned from the masters in the summer vacation. I think it is a really exquisite design. A class of problems that I could not solve before can be solved in such a simple and efficient way. I'm really sorry for the party if I don't share it. (party: rely on me, is it none of my business? Am I familiar with you?)

Let's take a look at an example, Hangdian 1232 unblocked project

First give you several towns on the map, these towns can be regarded as points, and then tell you which pairs of towns are directly connected by roads. The last thing to solve is the connectivity problem of the whole graph. For example, randomly give you two points, let you judge whether they are connected, or ask you how many connected branches the whole graph has, that is, it is divided into several independent blocks. For example, in the case of unimpeded engineering, asking how many roads still need to be built, the essence is to ask for several connecting branches. If it is 1 connected branch, it means that the points on the whole graph are connected, and there is no need to build a road; if it is 2 connected branches, just build 1 more road, and select a point from each of the two branches. Connect them, then all the points are connected; if it is 3 connected branches, then you only need to build two more roads...

Enter the data with the following set of data to illustrate

4 2 1 3 4 3

The first line tells you that there are a total of 4 points and 2 roads. The next two lines tell you that there is a way between 1 and 3, and a way between 4 and 3. Then the whole picture is divided into 1-3-4 and 2 parts. As long as another road is added, 2 is connected to any other point, and the smooth project is realized, then the output result of this group of data is 1. Well, let's program this function now. There are hundreds of towns, and there are no known how many roads, and there may be loops. How can this be good?

I didn't know it before, since I used and checked the set, hey, the effect is really good! Our whole family uses it!

The union search set consists of an integer array and two functions. The array pre[] records what the leading point of each point is, the function find is a search, and the join is a merge.

int pre[1000 ];

int find(int x)                                                                                                          //find the root node

    int r=x;

    while ( pre[r ] != r ) // return root node r

          r=pre[r ];

 

    int i=x , j ;

    while( i != r ) // path compression

    {

         j = pre[ i ];  // use temporary variable j to record the value of the superior before changing it 

         pre[ i ]= r ;  //Change the parent to the root node

         i=j;

    }

    return r ;

}

 

 

void join(int x,int y) //Determine whether xy is connected,

                                                                                             //If it is already connected, don't worry about it//If it is not connected, merge the connected branches where they are located,

{

    int fx=find(x),fy=find(y);

    if(fx!=fy)

        pre[fx ]=fy;

}

 

To explain the principle of union lookup, I'll give a more loving example. It is said that there are thousands of heroes of all kinds scattered on the rivers and lakes. They don't have a proper occupation, and they walk around with their swords on their backs all day. When they encounter people who are not the same as them, they will inevitably have a fight. But the heroes have an advantage in that they are loyal and never beat their friends. And they believe in "a friend's friend is my friend", as long as they can be connected through friendship, no matter how many turns they turn, they are considered their own. In this way, a community is formed on the rivers and lakes, which are connected in series through the friendship between the two. People who are not in the same group can't be connected through friendship anyway, so they can rest assured and fight to the death. But how can two people who didn't know each other know whether they belong to a circle of friends?

We can recommend a relatively famous person in each circle of friends as the representative of the circle, so that each circle can be named "Zidane Friends Team" "Ronaldo Friends Team"... two As long as people check with each other whether their captain is the same person, they can determine the relationship between friend and foe.

But there is still a problem. Heroes only know who their direct friends are. Many people don’t know the captain at all. To judge who their captain is, they can only ask aimlessly through their friends’ friendship: “You Is it the captain? Are you the captain?" In this way, the captain can't keep his face, and the efficiency is too low, and he may fall into an infinite loop. So the captain ordered to regroup. Everyone in the team implements a hierarchical system to form a tree-like structure. My captain is the root node, and the following are the second-level players and the third-level players. Everyone just needs to remember who their superiors are. When faced with judging friends and enemies, as long as you ask layer by layer to the top, you can determine who the captain is in a short time. Since all we care about is whether two people are connected, it doesn't matter how they are connected, what is the structure inside each circle, or even who the captain is. So we can let the captain regroup at will, as long as we don't make a mistake in the relationship between friend and foe. Thus, sects were born.

 

 

Let's take a look at the implementation of the union query. int pre[1000]; This array records who is the superior of each hero. The heroes are numbered from 1 or 0 (depending on the meaning of the question), and pre[15]=3 means that the superior of the 15th hero is the 3rd hero. If a person's superior is himself, it means that he is the head, and the search ends here. There are also lonely people who form their own faction, such as Ouyang Feng, then his superior is himself. Everyone only recognizes their superiors. For example, Hu Qingniu only knew that his superior was Yang Zuoshi. Who is Zhang Wuji? do not know! If you want to know who your head is, you can only check it level by level. The function find is used to find the master, and the meaning cannot be clearer (the path compression algorithm is ignored, and I will talk about it later).

int find(int x) //find the head of me (x)

{

    int r=x; //Entrust r to find the head

    while (pre[r ]!=r) //If r's superior is not r himself (that is to say, the hero he found is not the head ==)

    r=pre[r ] ; // r continues to look for his superior until he finds the head.

    return r ; //The master arrives~~~

}

Let's take a look at the join function, which is to connect a line between two points, so that all the points of the two plates where they were originally located can communicate with each other. This is easy to do on a graph, just draw a line. But we are now using the union check set to describe the situation in the martial arts, there is only one pre[] array, how to achieve it? Let's take the example of rivers and lakes, assuming that the current situation in the martial arts is as shown in the figure. Little Monk Xuzhu and Zhou Zhiruo are two characters that I like very much. Their ultimate bosses are Abbot Xuanci and Shitai Juejue, so they are obviously two camps. I didn't want them to fight with each other, so I said to them, "You two, let's be good friends." They saw my face and agreed. This agreement is no trivial matter, and the entire Shaolin and Emei faction can't fight. How can such a major change be realized and how many places need to be changed? It's actually very simple. I said to Abbot Xuanci: "Master, please change your superior to Shitai Miejue. In this way, the ultimate boss of all the original staff of the two factions is Shitai, so let's play a ball. Ah! Anyway, all we care about is connectivity, and the internal structure of the sect doesn't matter." Xuanci must be furious when he heard it: "Damn, why did I become her subordinate? Why not turn it around? I protest!" Protests are invalid, arranged by God, the biggest. Anyway, whoever joins has the same effect, so I just randomly assigned one. The meaning of this function is clear, right?

void join(int x,int y) //I want Xuzhu and Zhou Zhiruo to be friends

{

    int fx=find(x),fy=find(y); //The boss of Xuzhu is Xuanci, and the boss of Zhiruo MM is Zhuang

    if(fx!=fy) //Xuanci and Xie Xie are obviously not the same person

    pre[fx ]=fy; //The abbot had no choice but to be the servant of the master

}

Let's look at the path compression algorithm. The process of establishing a sect is to use the join function to connect two people together, and who is the subordinate of whom is completely random. I can't predict what the final tree-like structure will look like, and it's also possible for a long snake formation. This search efficiency will be relatively low. The ideal situation is that everyone's immediate superior is the head, and there is a two-level structure in total. You only need to search once to find the head. Even if it can't be done completely, it's best to get as close as possible. This leads to the path compression algorithm. Imagine such a scenario: two heroes who do not know each other meet and want to know if they can beat each other. So I hurriedly called my superior and asked, "Are you in charge?" The superior said, "I'm not. Who is my superior, you can ask him to take a look." All are Eunuch Cao of the East Factory. "Oh, it turned out to be remembering one's own people, Western Li and Western Li, and there are six groups of white-faced gourd babies in the next three camps!" Hand in hand to drink. "Wait, wait, two classmates, please stay, there are still things to do!" I stopped them. "Oh, by the way, we need to do path compression." The two woke up. The white-faced gourd baby called his superior sixth group leader: "Head of the group, I checked, and the leader of his puppets is Eunuch Cao. It's better for the puppets to worship under Eunuch Cao together, so as to save too much rank. Low, look for the head Mahuan in the future." "Well, it makes sense." The white-faced gourd baby then called the third battalion commander who had just visited... Fairy Gouweihua did the same thing. In this way, all the characters involved in the query are gathered under the direct leadership of Eunuch Cao. Each query is optimized, so the number of layers of the entire martial art tree will be maintained at a relatively low level. The code of path compression is easy to understand, but it doesn't matter if you don't understand it, just copy it and use it. In short, the function it achieves is exactly what it means.

 

This article was posted by Tony Fang. All interpretation rights belong to TonyFang. Mailto: [email protected]

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326520621&siteId=291194637