Take right and check set POJ1988 POJ2492

Source: Internet
Author: User

Simple and check set is very easy, with right and check set can also solve more problems, just more fun, to a problem warm-up. For the following knowledge, now when you have mastered the recursion and the path compression of the set.

POJ1988: Topic link http://poj.org/problem?id=1988

The main problem: there are N (n<=30,000) heap blocks, beginning each heap is a block. Block number 1–n. There are two kinds of actions:
m x y: Represents the heap where the square x is located, and it is stacked on the heap where Y is located.
c x: Ask the number of squares below the square x.
The operation has a maximum of P (p<=100,000) times. For each C operation, the output results.

It is necessary to check the par array in the set, and then add weights to the path to solve more complex problems by maintaining some other information.

For this problem, in addition to par array, we also have to open
Sum array: Records how many squares each heap contains. If parent[a] = A, then Sum[a] represents the number of blocks of the heap where A is located.
Under Array, Under[i] indicates how many squares are underneath the block I. The under array is updated when the heap is merged and the path is compressed.

First Look at initialization:

void Init () {for    (int i=0;i<maxn;i++) {        par[i]=i;        under[i]=0;        sum[i]=1;}    }

The focus is on the update of the under array, which should be understood below when the path is compressed:

What is the current wood block x below? It should be under[x] (this is the number of blocks under X in the current x heap), plus the under value of the root node (i.e. par[x]) of the current heap, and of course we all know that there is no block under the root node, under=0, but after we stack the X on another heap, So there is no block underneath the root node (i.e. par[x]) of the heap, and the under value is not 0. Therefore, as long as the path is compressed, for the current block x, the under value of the heap root node under[par[x]] is correct, then the updated under[x] is correct.

Update at merge time: The update is simple and obvious, the heap of U is placed all on the heap of V, then the increase in the number of blocks under U is the sum of the total number of blocks in the heap of V

Look again for path compression lookup:

/* Note here, Under[x] Originally from X down to par[x] a total of how many, if plus par[x] The following number, Under[x] is updated correctly. I don't care how much par[x] underneath, anyway, path compression will make under[par[x] guaranteed to be the correct value when executing this sentence. As for the y above, it is the layer recursion, it is obviously the final root after the path compression, so y is only used to par[x]=y, that is, the points encountered along the road to the final root (that is, the real path compression) This and update under value is not a half-dime relationship */int Find (int x) {    if (x==par[x]) return x;    int Y=find (par[x]);    UNDER[X]+=UNDER[PAR[X]];    return par[x]=y;}

You can see that the update for under is:always recursively to the final root of the heap, and then from the final root to the direction of X, step by step update, "from the final root can be under[par[x]" update correct ", then under[x] naturally correct, then the descendants of X (that is, par[a]=x a) can be updated correctly.

Merge:

After the path compression is complete, you can see a whole of you and V,//If you place the U above V, all the bricks in natural v will be counted to under[x] void Union (int u,int v) {    if ((U=find (u)) = = (V=find (v)))        return;    UNDER[U]+=SUM[V];    Par[u]=v;sum[v]+=sum[u];}
AC Code:

#include <stdio.h> #include <string.h> #include <algorithm>using namespace Std;const int maxn=30000+        10;int sum[maxn],par[maxn],under[maxn];void Init () {for (int i=0;i<maxn;i++) {par[i]=i;        under[i]=0;    Sum[i]=1; }}//note here, Under[x] is originally from X down to par[x] A total number of, that if plus//par[x] The following number, Under[x] is updated correctly. I don't care par[x] how much below,//anyway path compression will make the execution of this sentence to let Under[par[x] "guarantee is the correct value.    As for the above y, it is the layer of recursion to get, it is clear that the final root after the path compression, so//y is only used to par[x]=y, that is, all the points encountered along the road compression to the final root (that is, the real path compression)//This and update under not a half gross money relationship int Find (int x) {    if (X==par[x]) return x;    int Y=find (par[x]);    UNDER[X]+=UNDER[PAR[X]]; return par[x]=y;}        After the path compression is complete, you can see a whole of you and V,//If you place the U above V, all the bricks in natural v will be counted to under[x] void Union (int u,int v) {if ((U=find (u)) = = (V=find (v)))    return;    UNDER[U]+=SUM[V]; Par[u]=v;sum[v]+=sum[u];}    int main () {int i,j,p;    Char s[5];    Init ();    scanf ("%d", &p);        while (p--) {scanf ("%s", s);            if (s[0]== ' M ') {int A, B;            scanf ("%d%d", &a,&b);       Union (A, b); }else {int x;            scanf ("%d", &x);        Find (x);        To compress first, then query printf ("%d\n", under[x]); }} return 0;}

The Find function completes the "Four steps" of path compression and information update:

①par[x]==x recursive exit ② always recursively find the final root and record to Y③ Update current node and Father node information ④ return par[x]=y, complete path compression.

The information we maintain in the band and focus is generally the relationship between the current node x and its immediate father Par[x], so the information of x is updated with Par[x] in the third step.


Let's look at a more intuitive example below.

POJ2492 Topic Link: http://poj.org/problem?id=2492

The main topic: a total of n worms, numbering 1-n, give m relations, with X, y description, meaning: X and y have goodwill. After asking the m relationship, can you tell if there is a pair of bugs that are gay, yes or No.

As mentioned above, in the band right and check the set we generally maintain the current node x and its father's relationship, in this view, should think of what we want to maintain the information, that is: with a rel[] array to maintain x and par[x] gender relations, Rel[x]=0 said X and Par[x] is the same sex, Rex[x]=1 is the opposite sex, so we maintain this REL information while maintaining and checking the set.

First Look at initialization:

void Init (int n) {for         (int i=0;i<=n;i++) {            par[i]=i,rel[i]=0;        }    }
At first, every worm was gay and understandable.

When the Find function path is compressed, rel[] How to update it?

We first look at our purpose: because we are the way to compress, that is, the par of all the passing nodes point to the final root (set to Y), so in Find (x), the final rel[x] represents the gender relationship of X and Y (of course eventually par[x] will be equal to Y, rel[). From the blue above, we can know that the find function, Par[x] rel[] is ok (do not ask why, the above has been said very clearly, look at the "part of the Blue word"), so we are now known as X and Par[x] relationship, Par[x] and y relationship, It's easy to find the relationship between X and Y. Let's take a look at the list.


This watch is a good experience, and then you can understand it when you think about it.

We can see that the new rel[x] can be made by the previous rel[x] and Rel[par[x]], and equal to Rel[x]^rel[par[x]]. Our purpose is achieved.

Look at the code again:

int Find (int x) {        if (x==par[x]) return x;        int Y=find (par[x]);        REL[X]=REL[X]^REL[PAR[X]];        return par[x]=y;    }
Four steps are still the same. This maintains the rel[x].


For a pair of bugs, how do you know if they are gay?

This looks at the Union merge function, the first post code, followed by analysis.

BOOL Union (int u,int v) {    //returns true: Same sex; otherwise        the opposite sex int pu=find (u), Pv=find (v);        if (PU==PV) return rel[u]==rel[v];   If they are in the same set, then the two have the same gender relationship as their ancestors, stating that both sexes are        rel[pv]=! ( REL[U]^REL[V]);        Par[pv]=pu;        return false;    }
Note the return value meaning of the Union function.

set Pu=find (U), Pv=find (v) , for a given pair of worms U and V, there are two cases:

1. Both in the same set, PU==PV: That is good to do, also can not merge, and can be able to determine the gender relationship between the two, their rel[] are relative to the same root node, if you and your father is gay, my father and I are homosexual, then our sex relationship is not the same sex.

2. The two are not in the same set, PU!=PV: So u,v relationship we think is the opposite sex, and with this as a basis to merge two sets, merging two sets is actually merging PU and PV Ah, we put PU as the root of the collection into the set of the root of PV, namely PAR[PU]=PV,   But we also need to update REL[PU], that is, the relationship between Pu and PV, how to determine their relationship? First we know the relationship between U and Pu for rel[u],v and PV relationship for Rel[v], and we also want to ensure that you and V-specific, by the three relationships can determine the relationship between PU and PV!! Take a look at the list:


That first simple explanation one, U and Pu is same-sex, V and PV is same sex, u and V is opposite sex, then pu and PV nature is opposite sex.

So rel[pu]=! (Rel[u]^rel[v]).

That's about as much.


AC Code:

/* Take right and check set */#include <stdio.h> #include <string.h> #include <algorithm>using namespace Std;const int    maxn=2000+10;typedef struct wufset{int PAR[MAXN],REL[MAXN];        0 Gay, 1 straight void init (int n) {for (int i=0;i<=n;i++) {par[i]=i;rel[i]=0;        }} int Find (int x) {if (x==par[x]) return x;        int Y=find (par[x]);        REL[X]=REL[X]^REL[PAR[X]];    return par[x]=y;        } bool Union (int u,int v) {//returns true: Same sex; otherwise the opposite sex int pu=find (u), Pv=find (v);   if (PU==PV) return rel[u]==rel[v]; If they are in the same set, then the two have the same gender relationship as their ancestors rel[pv]=!        (Rel[u]^rel[v]);        Par[pv]=pu;    return false;    }}wufset;int Main () {int i,t,n,m,kcase=1;    Wufset s;    scanf ("%d", &t);        while (t--) {scanf ("%d%d", &n,&m);        S.init (n);        BOOL Yes=true;            while (m--) {int A, B;            scanf ("%d%d", &a,&b);        if (s.union (b)) Yes=false; } printf ("ScenaRio #%d:\n ", kcase++);        if (yes) printf ("No suspicious Bugs found!\n\n");    else printf ("suspicious bugs found!\n\n"); } return 0;}


Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Take right and check set POJ1988 POJ2492

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.