zoukankan      html  css  js  c++  java
  • 平面欧拉公式——zoj2589

    V-E+R=X+1:

     V:顶点数

     E:边数

     R:隔离的面数

     X:连通图数量

    对于圆来说:V=E=0, 当两圆相交时,V+2,E+4,两圆相切时V+1,E+2

    圆的边数E=圆上点数

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100005
    
    typedef double db;
    const db eps=1e-10;
    const db pi=acos(-1);
    int sign(db k){
        if (k>eps) return 1; else if (k<-eps) return -1; return 0;
    }
    int cmp(db k1,db k2){return sign(k1-k2);}
    int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内 
    struct point{
        db x,y;
        point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
        point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
        point operator * (db k1) const{return (point){x*k1,y*k1};}
        point operator / (db k1) const{return (point){x/k1,y/k1};}
        int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
        bool operator < (const point k1) const{
            int a=cmp(x,k1.x);
            if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
        }
        point unit(){db w=abs(); return (point){x/w,y/w};}
        db abs(){return sqrt(x*x+y*y);}
        db abs2(){return x*x+y*y;}
        db dis(point k1){return ((*this)-k1).abs();}
        point turn90(){return (point){-y,x};}
    };
    struct circle{
        point o;db r;
    };
    int checkposCC(circle k1,circle k2){// 返回两个圆的公切线数量
        if (cmp(k1.r,k2.r)==-1) swap(k1,k2);
        db dis=k1.o.dis(k2.o);  int w1=cmp(dis,k1.r+k2.r),w2=cmp(dis,k1.r-k2.r);
        if (w1>0) return 4; else if (w1==0) return 3; else if (w2>0) return 2; 
        else if (w2==0) return 1; else return 0;
    }
    vector<point> getCC(circle k1,circle k2){// 求两圆交点,沿圆 k1 逆时针给出 , 相切给出两个 
        int pd=checkposCC(k1,k2); if (pd==0||pd==4) return {};
        db a=(k2.o-k1.o).abs2(),cosA=(k1.r*k1.r+a-k2.r*k2.r)/(2*k1.r*sqrt(max(a,(db)0.0)));
        db b=k1.r*cosA,c=sqrt(max((db)0.0,k1.r*k1.r-b*b));
        point k=(k2.o-k1.o).unit(),m=k1.o+k*b,del=k.turn90()*c;
        return {m-del,m+del};
    } 
    
    point p[N];
    circle c[N];
    int n,cnt[N],tot,m;
    
    int F[N];
    int find(int x){
        return F[x]==x?x:F[x]=find(F[x]);
    }
    
    int main(){
        int t;cin>>t;
        while(t--){
            tot=m=0;
            
            cin>>n;
            for(int i=1;i<=n;i++)
                cin>>c[i].o.x>>c[i].o.y>>c[i].r;
            for(int i=1;i<=n;i++)F[i]=i;
            
            int X=n;
            for(int i=1;i<=n;i++){
                for(int j=i+1;j<=n;j++){
                        vector<point> v=getCC(c[i],c[j]);
                        if(v.size()==0 || v.size() && v[0]==v[1])continue;
                        for(auto pp:v)
                            p[++tot]=pp;
                        if(find(i)!=find(j)){
                            X--;
                            F[find(i)]=find(j);    
                        }
                    }
            }
            
            //去重 
            sort(p+1,p+1+tot);
            m=0;
            if(tot)m=1;
            for(int i=2;i<=tot;i++)
                if(!(p[i]==p[i-1]))
                    p[++m]=p[i];
            
            int V=m,E=0;
            for(int i=1;i<=m;i++){
                for(int j=1;j<=n;j++)
                    if(sign(p[i].dis(c[j].o)-c[j].r)==0)E++;
            }
    
            cout<<1+X-V+E<<'
    ';
        }
    }
  • 相关阅读:
    SQL Server 隐式转换引发的死锁
    C# List按某对象的属性分组 IGrouping
    C# 正则表达式获取json字符串中的键值
    .NET程序修改 ConfigurationManager 后,不需要重启IIS也可刷新Web.config配置文件
    相同结构的多个表合并到一个表的实现方法
    WCF系列_WCF影响客户端导出Excel文件的实现
    WCF系列_WCF如何选择不同的绑定
    WCF系列_WCF常用绑定选择
    JS生成URL二维码
    win 常用CMD命令备忘
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12354180.html
Copyright © 2011-2022 走看看