Weighted union search set

Keywords: Algorithm Graph Theory Union Find partitioning acm

A basic union search set

There are only two operations for the basic union query set, one is to find ancestors, and the other is to merge

int find(int x)
{
    if(x==pre[x]) return x;
    else return pre[x]=find(pre[x]);
}
void join(int x,int y)
{
    pre[find(x)]=find(y);
}

Two weighted union search set

  for weighted concurrent search set, it can maintain certain other relationships, such as distance, on our basis. Here we take Hangzhou Electric ~ HDUyyds as an example How Many Answers Are Wrong For example, in this topic, each sentence gives you the sum of the number between each point, and you have to judge which of these sentences are wrong and output the number of errors

  for the left and right boundaries given in each sentence, we can regard them as a point, and the sum of this interval is the weight above this edge, and we can convert this weight into a relative value to get the value of a pile of points about a point. After merging the points, we can get the relative value between the two points

  taking the above points a and b as an example, we can get that the fathers of a and b are fa and fb respectively, and the weight relationship between a and b is v. at this time, we combine the branch represented by a into our branch quotient of b. at this time, we can get the equation relationship v 1 + v x = v + v 2 v_{1} +v_{x} = v+v_2 v1 + vx = v+v2, so we update the weight of fa about fb

 code is as below

#include <iostream>
#define N 200005
using namespace std;
int f[N],value[N];
inline int find(int x) {
    if(x == f[x]) return x;
    else {
        int a = f[x];
        f[x] = find(f[x]);
        value[x] = value[x] + value[a];
        return f[x];
    }
}
int ans = 0;
int main() {
    int n,m;
    scanf ("%d%d",&n,&m);
    for (int i = 1;i <= n;i++) f[i] = i;
    int x,y,z;
    for (int i = 1;i <= m;i++) {
        scanf("%d%d%d",&x,&y,&z);
        int fl = find(x),fr = find(y);
        if(fr == fl) {
            if(value[x] - value[y] != z) ans++;
            else {
                f[fl] = fr;
                value[fl] = -value[x] + value[y] + z;
            }
        }
    }
    printf("%d",ans);
}

Three kinds of parallel search set

  category and search set actually means that all elements belong to a certain category, and then judge whether the result is true according to the logical relationship between each point, Category query template

  category merge query set is a branch of weight merge query set, but it can not be completely regarded as yes. Let me introduce two ways to write category merge query set

A writing method based on weighted parallel search set

#include <iostream>
using namespace std;
int f[100000],re[100000]; // re represents the corresponding relationship of each point, 0,1,2, 0 represents the same kind, 1 represents the predator-prey relationship, and 2 represents the predator-prey relationship
int n,m,ans;
int find(int a)
{
   int fa=f[a];
   if (a!=fa) {
       f[a]=find(fa);
       re[a]=(re[a]+re[fa])%3;
       return f[a];
   }
   else return fa;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) f[i] = i;
    for (int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&z,&x,&y);
        if ((x>n||y>n)||(z==2&&x==y)) {   //Two special cases
            ans++; continue;
        }
       if (z==1)
       {
           int f1=find(x),f2=find(y);
           if (f1==f2&&re[x]!=re[y])
           {
               ans++; continue;
           }
           else if(f1!=f2)
           {
               f[f1]=f2; re[f1]=(3-re[x]+re[y])%3;
             // Merge and query sets. They are of the same type, so they should be equal
           }
       }
       else {
           int f1=find(x),f2=find(y);
           if (f1==f2)
           {
             // If the merger has already been made, then if it is not a predator-prey relationship, it is an error
               int rela=(re[x]-re[y]+3)%3;
               if (rela!=1) {
                   ans++; continue;
               }
           }
           else {
               f[f1]=f2; re[f1]=(3-re[x]+re[y]+1)%3;
             // The species are different and there is a predation relationship, so 1 should be added
           }
       }
   }
    printf("%d\n",ans);
    return 0;
}

II. Writing method of multi open point space

  use i i i represents itself, i + n i+n i+n represents the prey, i + 2 ∗ n i+2*n i+2 * n indicates the strong prey

#include <iostream>
#define N 1010
using namespace std;
int f[N*3];
inline int find(int x){
    if(x == f[x]) return x;
    else{
        return f[x] = find(f[x]);
    }
}
int main() {
    int n,m,ans = 0;
    scanf("%d%d",&n,&m);
    for (int i = 1;i <= 3*n;i++) f[i] = i;
    for (int i = 1;i <= m;i++) {
        int x,y,z;
        scanf("%d%d%d",&z,&x,&y);
        if(x > n|| y > n||(z == 2&&x == y)) {ans++;continue;}
        if(z == 1) {
            if (find(x+n) == find(y) || find(y+n) == find(x)) {ans++;}
            else  {
                f[find(x)] = find(y);
                f[find(x+n)] = find(y+n);
                f[find(x+2*n)] = find(y+2*n);
            }
        } else {
            int fx = find(x);
            int fy = find(y);
            if (fx == fy|| find(x+2*n) == fy) {ans++;}
            else {
              f[find(x + n)] = fy;
              f[find(y+n)] = f[find(x+2*n)];
              f[find(y+2*n)] = fx;
            }
        }
    }
    printf("%d\n",ans);
}

Slip away, it's too delicious. The c + + experiment hasn't been written yet, and cf hasn't been scored yet (div3 can't ak all be spicy chicken, it's too delicious)

Posted by Stevis2002 on Wed, 03 Nov 2021 12:48:17 -0700