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;
}
原文地址:https://www.cnblogs.com/cjjsb/p/8551163.html