[SDOI2005]矩形 解题报告 (并查集)

2018-10-18 08:38:17


原题链接:

P2449 [SDOI2005]矩形

题目描述

现在我们在一个平面上画了n个矩形。每一个矩形的两边都与坐标轴相平行,且矩形定点的坐标均为整数。

现我们定义满足如下性质的图形为一个块:

1.每一个矩形都是一个块;

2.如果两个块有一段公共的部分,那么这两个块就会形成一个新的块,否则这两个块就是不同的。

示例:

图1中的矩形形成了两个不同的块。图2中的矩形形成了一个块。

任务:

请写一个程序:

1.从文本文件PRO.IN中读入各个矩形的顶点坐标;

2.找出这些矩形中不同的块的数目;

3.把结果输出到文本文件PRO.OUT中。

输入输出格式

输入格式:

 

文本文件PRO.IN的第一行包括一个整数n,1<=n<=7000,为矩形的数目。以下的n行为矩形顶点的坐标。

每一个矩形都是用四个整数来描述的:左下角的x坐标、左下角的y坐标、右上角的x坐标和右上角的y坐标。

所有的坐标都是不大于10000的非负整数。

 

输出格式:

 

在文本文件PRO.OUT中输出唯一的一个整数——这些矩形所形成的不同的块的数目。

 

输入输出样例

输入样例#1: 
9
0 3 2 6
4 5 5 7
4 2 6 4
2 0 3 2
5 3 6 4
3 2 5 3
1 4 4 7
0 0 1 4
0 0 4 1
输出样例#1:
2

♦题目大意:
输入n个矩形,若两个矩形重合则将这两个矩形合并在一起,最后问一共有几块区域?
注意:两个矩形边与边重合能合成一块,而两个矩形点与点重合则不行!
♦思路:
显然,一个并查集不就搞定了吗?
可是!这道题的难点并不是并查集本身吧,更多的是怎么判断这两个矩形重合!
一开始,我的思路是将a矩形内的点全部标记一下,再枚举b矩形,看b矩形中有a矩形标记
过的几个点,若点大于1,则表示重合。虽然,这个方法是可行的,但是看数据范围,矩形
的坐标是不大于10000的非负整数,啊,显然就炸掉了!那怎么办呢?我我又很懒,那懒人
有懒方法,嗯,就从反向考虑吧!

如果b矩形的4个点的横坐标都大于a矩形的下点横坐标/都小于a矩形的上点横坐标..(依
旧很懒,如图,红色为a矩形,绿色为b矩形)

这4种情况则是不重合,那么怎么判断只有一个点重合的情况呢?其实只要特判一下就好了!

这样,这道题就AC了!


#include<bits/stdc++.h>
using namespace std;

int n;
struct Squ{int x,y,xx,yy;}squ[7000+10];
int fa[7000+10]; 
int ans[7000+10],oo;
int fi,fj;
int c;

int jud(int d,int dd)
  {
     int xf1=squ[d].x,yf1=squ[d].y,xf2=squ[d].xx,yf2=squ[d].yy;
     int xl1=squ[dd].x,yl1=squ[dd].y,xl2=squ[dd].xx,yl2=squ[dd].yy;
     if((xl1<xf1&&xl2<xf1)||(xl1>xf2&&xl2>xf2)||(yl1<yf1&&yl2<yf1)||(yl1>yf2&&yl2>yf2)) return 0;
     if((xl1==xf2&&yl1==yf2)||(xl1==xf2&&yl2==yf1)||(xl2==xf1&&yl1==yf2)||(xl2==xf1&&yl2==yf1)) return 0;
     return 1;
  }

int find(int x)
  {
      if(fa[x]==x) return x;
      return fa[x]=find(fa[x]);
  }

int main()
  {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        scanf("%d%d%d%d",&squ[i].x,&squ[i].y,&squ[i].xx,&squ[i].yy);
      for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=2;i<=n;i++)
        for(int j=1;j<=i-1;j++)
          {
              c=jud(j,i);
            if(c==1)
                {
                    fi=find(i);
                    fj=find(j);
                    if(fi!=fj) fa[fi]=fj;
              }
        }
    for(int i=1;i<=n;i++)
      {
          fa[i]=find(i);
        ans[fa[i]]++;
      }
    for(int i=1;i<=n;i++)
      if(ans[i]>0) oo++;
    //for(int i=1;i<=n;i++)
      //printf("%d",fa[i]);
    printf("%d",oo);
    return 0;  
  } 



猜你喜欢

转载自www.cnblogs.com/gyu0327/p/9808517.html