zoukankan      html  css  js  c++  java
  • POJ 1988&&2236

      并查集,如果只是朴素的路径压缩,那么也就是一句话的事情。

      但是,一般都没有这种仁慈的裸题(假的,多了去了)

      1988:带权并查集,贼鸡儿像Luogu的那道杨威利的并查集(好像是叫银河英雄传说)

      开两个数组,down[x]表示标号为x的箱子下面有多少个箱子,len[x]表示以x点为根(即被压在最底部的箱子)的箱子总个数是多少。

      因此我们在合并时,要把fx的父节点更新为fy,同时还要更新down[fx]和len[fy]。当然,最容易忽略的是把len[fx]清零。

      对于具体的down[x]的更新,只需要在getfather的时候递归操作即可。

      CODE

    #include<cstdio>
    using namespace std;
    const int N=30005;
    int down[N],len[N],father[N],n,p,i,x,y;
    char opt;
    inline void read(int &x)
    {
        x=0; int flag=1; char ch=getchar();
        while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); }
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        x*=flag;
    }
    inline void write(int x)
    {
        if (x<0) putchar('-'),x=-x;
        if (x/10) write(x/10);
        putchar(x%10+'0');
    }
    inline int getfather(int k)
    {
        if (father[k]==k) return k;
        int fa=father[k];
        father[k]=getfather(father[k]);
        down[k]+=down[fa];
        return father[k];
    }
    int main()
    {
        read(p);
        for (i=1;i<N;++i)
        father[i]=i,len[i]=1,down[i]=0;
        while (p--)
        {
            while (opt=getchar(),opt!='M'&&opt!='C') opt=getchar();
            if (opt=='M')
            {
                read(x),read(y);
                int fx=getfather(x),fy=getfather(y);
                if (fx!=fy)
                {
                    father[fx]=fy;
                    down[fx]+=len[fy];
                    len[fy]+=len[fx];
                    len[fx]=0;
                }
            } else read(x),getfather(x),write(down[x]),putchar('
    ');
        }
        return 0;
    }

      2236:一道基础的并查集维护联通关系的题目。

      每打开一台计算机,就扫描过其他所有的打开的计算机。如果他们之间的距离小于等于d就合并。

      查询的时候并查集查询father即可。

      CODE

    #include<cstdio>
    using namespace std;
    const int N=1005;
    int x[N],y[N],n,d,father[N],i,num,a,b;
    bool vis[N];
    char opt;
    inline void read(int &x)
    {
        x=0; char ch=getchar(); int flag=1;
        while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); }
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        x*=flag;
    }
    inline int getfather(int k)
    {
        return father[k]==k?k:father[k]=getfather(father[k]);
    }
    int main()
    {
        read(n); read(d);
        for (i=1;i<=n;++i)
        read(x[i]),read(y[i]),father[i]=i;
        while (scanf("%c",&opt)!=EOF)
        {
            if (opt=='O')
            {
                read(num);
                if (vis[num]) continue;
                vis[num]=1;
                for (i=1;i<=n;++i)
                {
                    if (num==i) continue;
                    if (vis[i]&&(x[i]-x[num])*(x[i]-x[num])+(y[i]-y[num])*(y[i]-y[num])<=d*d) father[getfather(i)]=getfather(num);
                }
            } else
            {
                read(a); read(b);
                if (!vis[a]||!vis[b]) { puts("FAIL"); continue; }
                if (getfather(a)==getfather(b)) puts("SUCCESS"); else puts("FAIL");
            }
        }
        return 0;
    }
  • 相关阅读:
    BZOJ1049 [HAOI2006]数字序列0
    UOJ265 【NOIP2016】愤怒的小鸟
    #include <deque>
    #include <queue>
    #include <vector>
    #include <set>
    #include <map>
    BZOJ1217:[HNOI2003]消防局的设立
    浅谈贪心
    CF1060B:Maximum Sum of Digits
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8551163.html
Copyright © 2011-2022 走看看