弄了一天了,也不知道哪里有问题
留着再说吧
/* 构图:枚举每个点作为原点,把原点和每个圆的切点也加进去,极角排序, 扫描时用一个数组记录当前在那些圆的角度范围内 构造出图后求联通块个数 */ #include<bits/stdc++.h> using namespace std; #define N 5005 typedef double db; const db eps=1e-6; 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);} struct point{ db x,y; int color,id,flag; 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 getP() const{return sign(y)==1||(sign(y)==0&&sign(x)>=0);} point turn90(){return (point){-y,x};} db abs(){return sqrt(x*x+y*y);} point unit(){db w=abs();return (point){x/w,y/w};} }; db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;} int comp(point k1,point k2){ if(k1.getP()==k2.getP())return sign(cross(k1,k2))>0; return k1.getP()<k2.getP(); } struct circle{ point o; db r; int color; }; vector<point> TangentCP(circle k1,point k2){// 求点到圆的切点,沿圆 k1 逆时针给出 db a=(k2-k1.o).abs(),b=k1.r*k1.r/a,c=sqrt(max((db)0.0,k1.r*k1.r-b*b)); point k=(k2-k1.o).unit(),m=k1.o+k*b,del=k.turn90()*c; return {m-del,m+del}; } int n,m; point p[N],pp[N]; circle c[N]; int f[N],tot,in[N],cnt; vector<int>G[N]; void solve(int id){ tot=cnt=0; memset(in,0,sizeof in); memset(f,0,sizeof f); for(int i=1;i<=n;i++) if(i!=id){ pp[++tot]=p[i]-p[id]; pp[tot].id=i; } for(int i=1;i<=m;i++){ circle k1=c[i]; k1.o=k1.o-p[id]; vector<point> v=TangentCP(k1,(point){0,0}); if(sign(cross(v[0],v[1]))<0) swap(v[0],v[1]); pp[++tot]=v[0]; pp[tot].color=i; pp[tot].flag=1; pp[++tot]=v[1]; pp[tot].color=i; pp[tot].flag=0; } sort(pp+1,pp+1+tot,comp); for(int i=1;i<=tot;i++)pp[i+tot]=pp[i]; for(int i=1;i<=tot*2;i++){ if(pp[i].color==0){ if(cnt!=0)f[pp[i].id]=1; } else { int color=pp[i].color; if(in[color]==1){ if(pp[i].flag==0) in[color]=0,cnt--; } else if(pp[i].flag==1) in[color]=1,cnt++; } } for(int i=1;i<=n;i++) if(!f[i]){ G[i].push_back(id); G[id].push_back(i); } } int vis[N],ans; void dfs(int u){ vis[u]=1; for(auto v:G[u]) if(!vis[v])dfs(v); } int main(){ int t;cin>>t; while(t--){ memset(vis,0,sizeof vis); ans=0; cin>>n>>m; for(int i=1;i<=n;i++)G[i].clear(); for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y); for(int i=1;i<=m;i++)scanf("%lf%lf%lf",&c[i].o.x,&c[i].o.y,&c[i].r); if(m==0){ puts("0");continue; } for(int i=1;i<=n;i++) solve(i);//以i为原点 for(int i=1;i<=n;i++) if(!vis[i])++ans,dfs(i); cout<<ans-1<<'\n'; } } /* 3 5 4 0 0 2 2 2 -2 -2 2 -2 -2 2 0 1 0 2 1 0 -2 1 1 1 0.5 4 1 0.9 0.9 0.9 -0.9 -0.9 0.9 -0.9 -0.9 0 0 1 5 2 0 0 2 -2 -2 2 1.9 1.9 -1.9 -1.9 1 1 1 -1 -1 1 */