NOIP 考前 并查集复习

Posted on 2016-10-28 13:51  yyjxx2010xyu  阅读(163)  评论(0编辑  收藏  举报

 

POJ 1182

把一个点拆成x,x+n,x+2*n,x吃y可以表示认为x,y+n是一类的,x+n,y+2*n是一类,x+2*n,y是一类。

 1 #include <cstdio>
 2 
 3 const int Maxn=50100;
 4 int F[Maxn*3],n,k,Type,x,y,Ans;
 5 int Get(int x) {return F[x]==x?x:F[x]=Get(F[x]);}
 6 int main()
 7 {
 8     scanf("%d%d",&n,&k);
 9     for (int i=1;i<=3*n;i++) F[i]=i;
10     for (int i=1;i<=k;i++)
11     {
12         scanf("%d%d%d",&Type,&x,&y);
13         if (x>n || y>n || (x==y && Type==2))
14         {
15             Ans++;
16             continue;
17         }
18         
19         if (Type==1)
20         {
21             if (Get(x)==Get(y+n) || Get(x)==Get(y+2*n))
22             {
23                 Ans++;
24                 continue;
25             }
26             F[Get(x)]=Get(y);
27             F[Get(x+n)]=Get(y+n);
28             F[Get(x+2*n)]=Get(y+2*n);
29         } else 
30         {
31             if (Get(x)==Get(y) || Get(x)==Get(y+2*n))
32             {
33                 Ans++;
34                 continue;
35             }
36             F[Get(x)]=Get(y+n);
37             F[Get(x+n)]=Get(y+2*n);
38             F[Get(x+2*n)]=Get(y);
39         }
40     }
41     printf("%d\n",Ans);
42     return 0;
43 }
POJ 1182

 

HDU 3047

Sum[x]表示fa[x]和x的差. 带权并查集

#include <cstdio>

int Sum[50010],Father[50010],n,m,Count,u,v,w;
int Get_Father(int x)
{
    if (x==Father[x]) return x;
    int Tmp=Get_Father(Father[x]);
    Sum[x]+=Sum[Father[x]];
    return Father[x]=Tmp;
}
int main()
{
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        for (int i=0;i<=n;i++) Father[i]=i,Sum[i]=0;
        Count=0;
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            int fu=Get_Father(u),fv=Get_Father(v);
            if (fu!=fv) 
            {
                Father[fu]=fv;
                Sum[fu]=Sum[v]+w-Sum[u];
            } else 
            {
                if (Sum[u]-Sum[v]!=w)
                    Count++;
            }
        }
        printf("%d\n",Count);
    }
    return 0;
}
HDU 3047

 

BZOJ 1202

带权并查集

 1 #include <cstdio>
 2 int KASE,n,m,u,v,w;
 3 int Father[20010],Sum[20010]; 
 4 int Get_Father(int x)
 5 {
 6     if (x==Father[x]) return x;
 7     int Tmp=Get_Father(Father[x]);
 8     Sum[x]+=Sum[Father[x]];
 9     Father[x]=Tmp;
10     return Tmp;
11 }
12 int main()
13 {
14     scanf("%d",&KASE);
15     for (int Kase=1;Kase<=KASE;Kase++)
16     {
17         scanf("%d%d",&n,&m); bool flag=false;
18         for (int i=0;i<=n;i++) Father[i]=i,Sum[i]=0;
19         for (int i=1;i<=m;i++)
20         {
21             scanf("%d%d%d",&u,&v,&w);
22             int fu=Get_Father(u-1),fv=Get_Father(v);
23             if (fu==fv)
24             {
25                 if (Sum[u-1]-Sum[v]!=w) 
26                 {
27                     flag=true;
28                     break;
29                 }
30             } else
31             {
32                 Father[fu]=fv;
33                 Sum[fu]=Sum[v]-Sum[u-1]+w;
34             }
35         }
36         puts(flag?"false":"true");
37     }
38     return 0;
39 }
BZOJ 1202