3282: 向往的气球

题目描述
一年一度的计控ACM院赛即将来临。除了ACMers以外,志愿者们也非常的忙碌。他们需要将各种颜色的气球分配给A掉相应题目的队伍。现在,所有比赛队伍的成员都处在一个房间中,这个房间是一个二维坐标系,大小为1000行x1000列。
每一个坐标对应着空座位或某个参赛队伍。每一分钟,志愿者们都应该把所有的气球聚集在一起。志愿者将会被告知把气球送到哪里。为了保证工作的效率,对于两个坐标(x1,y1)和(x2,y2),如果|x1-x2|不大于k 或者 |y1-y2|不大于k,则这两个坐标的气球由同一个志愿者配送。你能知道最少需要多少志愿者,才能配送完所有的气球吗?
输入
第一行包含一个整数T,表示有T组数据。
对于每一组数组,这里将有n+1行
第一行:输入两个整数n,k; n表示气球的数量,k表示题目中的k值
接下来的n行中,每一行包含两个整数r,c。表示气球应该被送往r行,c列。请注意坐标可能会相同。
题目中保证:T<=100,1<=n<=10000,1<=k,r,c<=1000
输出
对于每一组数据,你需要输出一行
输出最少需要的志愿者数量

样例输入

2
3 5
1 1
10 6
15 20
2 5
1 1
7 7

样例输出

1
2

距离合适的可以都交给一个人送,依据距离条件可以划分成若干集合。
并查集可以做到。

http://202.194.119.110/problem.php?id=3282

错误代码// 按照Y排序后序号会变,还傻傻看了一个下午,充分证明我是超级菜。
#include<bits/stdc++.h>
using namespace std;
typedef struct
{
    int x;
    int y;
    int  vis;
}dian;

dian d[100005];
int  f[100005];
 bool cmp1(dian a,dian b)
 {
     return a.x<b.x;
 }
 bool cmp2(dian a,dian b)
 {
     return a.y<b.y;
 }
int getf(int a)
{
        return f[a]==a?a:f[a]=getf(f[a]);

}

void marge(int a,int b)
{
    int aa,bb;
    aa=getf(a);
    bb=getf(b);
    if(aa!=bb)
        f[bb]=aa;
}


int main()
{
    int t,n,k;
    cin>>t;
    while(t--)
    {
            cin>>n>>k;
             for(int i=1;i<=n;i++)
             {
                cin>>d[i].x>>d[i].y;
                d[i].vis=i;
                f[i]=i;
             }


            sort(d+1,d+1+n,cmp1);

            for(int i=2;i<=n;i++)
            {
                if(d[i].x-d[i-1].x<=k)
                    marge(i-1,i);        //要合并的是排完序后的序号
            }

//            for(int i=1;i<=n;i++)
//                cout<<i<<"***"<<f[i]<<endl;

            sort(d+1,d+1+n,cmp2);

            for(int i=2;i<=n;i++)
            {
                if(d[i].y-d[i-1].y<=k)
                    marge(i-1,i);    //要合并的是排完序后的序号,第二次排序后与第一次序号不同了
                            //不能仅仅依靠数组下标来划分集合
            }
//            for(int i=1;i<=n;i++)
//                cout<<i<<"***"<<f[i]<<endl;
//

             int sum=0;
              for(int i=1;i<=n;i++)
              {
                  if(f[i]==i)
                    sum++;
                    //cout<<i<<"***"<<f[i]<<endl;
              }
             cout<<sum<<endl;


    }

    return 0;
}

正确的代码
#include<bits/stdc++.h>
using namespace std;
typedef struct
{
    int x;
    int y;
    int  vis;
}dian;

dian d[100005];
int  f[100005];
 bool cmp1(dian a,dian b)
 {
     return a.x<b.x;
 }
 bool cmp2(dian a,dian b)
 {
     return a.y<b.y;
 }
int getf(int a)
{
    if(a==f[a])
        return a;
    else
    {
        return f[a]=getf(f[a]);
    }
        //return f[a]==a?a:f[a]=getf(f[a]);

}

void marge(int a,int b)
{
    int aa,bb;
    aa=getf(d[a].vis);//不能仅仅依靠数组下标来划分集合
    bb=getf(d[b].vis);//他原来是几号就搜几号
    if(aa!=bb)
        f[bb]=aa;
}


int main()
{
    int t,n,k;
    cin>>t;
    while(t--)
    {
            cin>>n>>k;
             for(int i=1;i<=n;i++)
             {
                cin>>d[i].x>>d[i].y;
                d[i].vis=i; //保存 唯一的身份
                f[i]=i;
             }


            sort(d+1,d+1+n,cmp1);

            for(int i=2;i<=n;i++)
            {
                if(d[i].x-d[i-1].x<=k)
                    marge(i-1,i);
            }

//            for(int i=1;i<=n;i++)
//                cout<<i<<"***"<<f[i]<<endl;

            sort(d+1,d+1+n,cmp2);

            for(int i=2;i<=n;i++)
            {
                if(d[i].y-d[i-1].y<=k)
                    marge(i-1,i);
            }
//            for(int i=1;i<=n;i++)
//                cout<<i<<"***"<<f[i]<<endl;


             int sum=0;
              for(int i=1;i<=n;i++)
              {
                  if(f[i]==i)
                    sum++;
                   // cout<<i<<"***"<<f[i]<<endl;
              }
             cout<<sum<<endl;


    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42820722/article/details/82389873