UVA 10301 (最大粘合的换有多少个,并查集)



Rings and Glue

Time Limit: 1 second

Memory Limit: 32 MB

 

Little John is in big trouble. Playing with his different-sized (and colored!) rings and glue seemed such a good idea. However, the rings now lay on the floor, glued together with some-thing that will definitely not come off with water. Surprisingly enough, it seems like no rings are actually glued to the floor, only to other rings. How about that!

 

You must help Little John to pick the rings off the floor before his mom comes home from work. Since the glue is dry by now, it seems like an easy enough task. This is not the case. Little John is an irrational kid of numbers, and so he has decided to pick up the largest component (most rings) of glued-together rings first. It is the number of rings in this largest component you are asked to find. Two rings are glued together if and only if they overlap at some point but no rings will ever overlap in only a single point. All rings are of the doughnut kind (with a hole in them). They can however, according to Little John, be considered “infinitely thin”.

 

Input

Input consists of a number (>0) of problems. Each problem starts with the number of rings, n, where £ 100. After that, n rows follow, each containing a ring’s physical attributes. That is, 3 floating point numbers, with an arbitrary number of spaces between them, describing the x coordinate and y coordinate for its center and its radius. All floating point numbers fit into the standard floating point type of your favorite programming language (e.g., float for C/C++). Input ends with a single row with the integer -1.

 

Output

Output consists of as many grammatically correct answers as there were problems, each answer, on a separate line, being ‘The largest component contains X ring(s).’ where Xis the number of rings in the largest component.

 

Sample Input

4

0.0 0.0 1.0

-1.5 -1.5 0.5

1.5 1.5 0.5

-2.0 2.0 3.5

3

3.0 2.0 2.0

0.0 -0.5 1.0

0.0 0.0 2.0

5

-2.0 0.0 1.0

1.0 -1.0 1.0

0.0 1.0 0.5

2.0 0.0 1.0

-1.0 1.0 1.0

-1

 

Sample Output

The largest component contains 4 rings.

The largest component contains 2 rings.

The largest component contains 3 rings.


题目大意:

给你N个圆的圆心坐标和半径,判断相交最多的那一堆圆有多少个?,相交在这定义为圆心距大于等于两圆半径距离之差的绝对值,小于等于两圆半径之和。

解题思路:

       并查集。坑点是输入的N可以为0,且为0是rings,只有为1是ring。合并集合时要用到一个rank,不然集合相并会混乱。


代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#define eps 1e-6

using namespace std;

struct circle{
    double x,y,r;
    circle(double x0=0,double y0=0,double r0=0){
        x=x0,y=y0,r=r0;
    }
};

const int maxn = 120;
int n,parent[maxn],rank[maxn],cnt[maxn];
bool visited[maxn];
circle cir[maxn];

void initial(){
    for(int i=0;i<=n;i++){
        parent[i]=i;
        rank[i]=cnt[i]=1;
    }
}

int getRoot(int k){
    if(k!=parent[k]) parent[k]=getRoot(parent[k]);
    return parent[k];
}

void Union(int a,int b){
    if(rank[a]<rank[b]){
        parent[a]=b;
        cnt[b]+=cnt[a];
    }
    else{
        if(rank[a]==rank[b])
            rank[a]++;
        parent[b]=a;
        cnt[a]+=cnt[b];
    }
}

void solve(){
    for(int i=1;i<=n;i++){
        scanf("%lf%lf%lf",&cir[i].x,&cir[i].y,&cir[i].r);
    }
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            double a=(cir[i].x-cir[j].x)*(cir[i].x-cir[j].x);
            double b=(cir[i].y-cir[j].y)*(cir[i].y-cir[j].y);
            if((cir[i].r+cir[j].r-sqrt(a+b))>-eps&&sqrt(a+b)-fabs(cir[i].r-cir[j].r)>-eps){
                int p=getRoot(i),q=getRoot(j);//因为可以相等,所以大于负的eps
                if(p!=q) Union(p,q);
            }
        }
    }
}

void output(){
    int maxcnt=0;
    for(int i=1;i<=n;i++){
        if(maxcnt<cnt[i]) maxcnt=cnt[i];
    }
    if(maxcnt==1)
        printf("The largest component contains %d ring.\n",maxcnt);//为0时也是复数输出
    else
        printf("The largest component contains %d rings.\n",maxcnt);
}

int main(){
    while(~scanf("%d",&n)&&n>=0){//存在0的情况
        initial();
        solve();
        output();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值