ACdream1237

#include<iostream>
#include<cstdio>
#include<set>
#include<cmath>
#include<cstring>
using namespace std;
const double eps = 1e-8;
 
struct p{
    double first,second;
};
 
int n,father[55];
double x[55],y[55],r[55];
bool used[55];
set<p> s,v[55];
 
inline bool operator<(const p& lhs, const p& rhs) {
    if (fabs(lhs.first - rhs.first) > 1e-8) {
        return lhs.first < rhs.first;
    } else if (fabs(lhs.second - rhs.second) > 1e-8) {
        return lhs.second < rhs.second;
    } else {
        return false;
    }
}
 
int Find(int xi){
    if(father[xi]==xi) return xi;
    return father[xi]=Find(father[xi]);
}
 
void Union(int xi,int yi){
    int xx=Find(xi),yy=Find(yi);
    if(xx!=yy) father[xx]=yy;
}
 
inline double po(double xi){
    return xi*xi;
}
 
double dis(int i,int j){
    return sqrt(po(x[i]-x[j])+po(y[i]-y[j]));
}
 
bool cross(int i,int k){
    double d=dis(i, k);
    if(d<fabs(r[i]-r[k])-eps || d>r[i]+r[k]+eps) return false;
    return true;
}
 
void solve(int k){
    double x1=x[k],y1=y[k],r1=r[k],x2,y2,r2;
    for(int i=0;i<k;i++){
        if(cross(i,k)){
            //cout<<i<<" "<<k<<endl;
            Union(i, k);
            p ans1,ans2;
            x2=x[i],y2=y[i],r2=r[i];
            double a=x2-x1,b=y2-y1,c=(po(r1)-po(r2)+po(x2)+po(y2)-po(x1)-po(y1))/2.0;
            if(y1==y2){
                double x=c/a;
                ans1.first=ans2.first=x;
                double d=sqrt(po(r1)-po(x-x1));
                ans1.second=y1+d;
                ans2.second=y1-d;
            }
            else {
                double A,B,C,D;
                A=po(a/b)+1.0;
                B=2.0*(y1*a/b-a*c/b/b-x1);
                C=po(x1)+po(c/b)-2.0*y1*c/b+po(y1)-po(r1);
                D=po(B)-4*A*C;
                ans1.first=(-B+sqrt(D))/A/2.0;ans1.second=(c-a*ans1.first)/b;
                ans2.first=(-B-sqrt(D))/A/2.0;ans2.second=(c-a*ans2.first)/b;
            }
            s.insert(ans1);
            s.insert(ans2);
            v[k].insert(ans1);v[i].insert(ans1);
            v[k].insert(ans2);v[i].insert(ans2);
        }
    }
}
 
void init(){
    memset(used, false, sizeof(used));
    s.clear();
    for(int i=0;i<n;i++){
        v[i].clear();
        father[i]=i;
    }
}
 
int main(){
    while(~scanf("%d",&n)){
        init();
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf",&x[i],&y[i],&r[i]);
            solve(i);
        }
        int e=0,empty=0;
        for(int i=0;i<n;i++){
            e+=v[i].size();
            used[Find(i)]=true;
        }
        for(int i=0;i<n;i++) if(used[i]) empty++;
        //cout<<e<<" "<<s.size()<<" "<<empty<<endl;
        printf("%d\n",e-s.size()+empty+1);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值