SDNU——1016.矩形合并(并查集)

Description
平面上有n个矩形,给定每个矩形的左下角坐标和右上角坐标。如果把重合的矩形合并成一个图形,则经过合并之后,还剩多少个图形?
Input
第1行:一个整数n(1 <= n <= 100),表示矩形的数量。
第2至第n+1行:每行有4个整数(不会超过int),第i 行中的4个数字分别表示编号为i-1的矩形的左下角x、y坐标与右上角x、y坐标。
Output
合并后剩余的图形数。
Sample Input

3
0 0 2 2
1 1 4 4
4 4 5 5

Sample Output

2

Hint
相邻不重合的图形不合并

BZ:本来想着暴力种类的,后来发现是一个并查集模板题,我就看了看,

//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std ;
typedef long long ll;
#define MAXN 200000005
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll

struct student
{
    int a, b, c, d;
};

int pre[105];
void init()//如果集合i的上级是自己,说明自己就是老大,直接返回下标
{
    for(int i=0; i<105; ++i)
        pre[i] = i;
}

int Find(int x)//查找老大
{
    if(pre[x] == x)
        return x;
    else
        return Find(pre[x]);
}

int join(int x, int y)//x和y建立下属关系。
{
    int fx = Find(x), fy = Find(y);
    if(fx != fy)
        pre[fx] = fy;
    return 0;
}

int main()
{
    int n;
    struct student stu[105];
    while(~scanf("%d", &n))
    {
        memset(stu, 0, sizeof(stu));
        memset(pre, 0, sizeof(pre));
        for(int i=0; i<n; ++i)
            scanf("%d %d %d %d", &stu[i].a, &stu[i].b, &stu[i].c, &stu[i].d);
        init();
        for(int i=0; i<n; ++i)
        {
            for(int j=i+1; j<n; ++j)
            {
                if(stu[i].a<stu[j].c && stu[i].b<stu[j].d && stu[i].c>stu[j].a && stu[i].d>stu[j].b)
                    join(i, j); //重合就建立关系
            }
        }
        int sum=0;
        for(int i=0; i<n; ++i)
            if(pre[i] == i)//把大佬们全加起来。
                sum++;
        cout << sum << '\n';
    }
    return 0;
}

其实我还翻了一篇并查集的入门,看到一张图很有意思啊,,,,
SDNU——1016.矩形合并(并查集)_第1张图片
并查集被拟化成了江湖门派的斗争(致敬一下金庸先生)
下面是这位仁兄的博客链接:并查集(入门)hhhh
下面上一段路径压缩的代码:

int tofind(int x)
{
    int r=x;
    if (fa[r] != r)//找老大
        fa[r] = tofind(fa[r]);
    int i=x, j;
    while(i != r)
    {
        j = pre[i];//在改变上级之前用j存下下级的值
        pre[i] = r;//把上级变为根节点
        i = j;
    }
    return r;//返回老大
}

你可能感兴趣的:(SDNUOJ)