【模板】【两圆相交】【平面欧拉定理】zoj2589
题目链接:https://zoj.pintia.cn/problem-sets/91827364500/problems/91827366088
欧拉定理 V - E + R = 2 (V:顶点 E:边 R:面)
两圆相交模板:
1 // p1,p2是交点 2 inline bool operator<(const Point& lhs, const Point& rhs) { 3 if (fabs(lhs.x - rhs.x) > 1e-8) { 4 return lhs.x < rhs.x; 5 } else if (fabs(lhs.y - rhs.y) > 1e-8) { 6 return lhs.y < rhs.y; 7 } else { 8 return false; 9 } 10 } 11 double dis(Point a,Point b){ 12 return sqrt( (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); 13 } 14 double sqr(double x){return x*x;} 15 bool intersection(Point o1, double r1, Point o2, double r2, Point& p1, Point& p2) { 16 double d = dis(o1, o2); 17 if (d < fabs(r1 - r2) - eps || d > r1 + r2 + eps) { 18 return false; 19 } 20 double cosa = (sqr(r1) + sqr(d) - sqr(r2)) / (2 * r1 * d); 21 double sina = sqrt(max(0.0, 1.0 - sqr(cosa))); 22 p1 = p2 = o1; 23 p1.x += r1 / d * ((o2.x - o1.x) * cosa + (o2.y - o1.y) * -sina); 24 p1.y += r1 / d * ((o2.x - o1.x) * sina + (o2.y - o1.y) * cosa); 25 p2.x += r1 / d * ((o2.x - o1.x) * cosa + (o2.y - o1.y) * sina); 26 p2.y += r1 / d * ((o2.x - o1.x) * -sina + (o2.y - o1.y) * cosa); 27 return true; 28 }
代码:
1 //欧拉定理 V - E + R = 2 (V:顶点 E:边 R:面) 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define eps 1e-6 5 const int N = 60; 6 typedef long long ll; 7 struct Point{ 8 double x,y; 9 }; 10 struct Circle{ 11 Point o; 12 double r; 13 }c[N]; 14 set<Point> st1[N],st2[N]; 15 int fa[N],E[N]; 16 // p1,p2是交点 17 inline bool operator<(const Point& lhs, const Point& rhs) { 18 if (fabs(lhs.x - rhs.x) > 1e-8) { 19 return lhs.x < rhs.x; 20 } else if (fabs(lhs.y - rhs.y) > 1e-8) { 21 return lhs.y < rhs.y; 22 } else { 23 return false; 24 } 25 } 26 double dis(Point a,Point b){ 27 return sqrt( (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); 28 } 29 double sqr(double x){return x*x;} 30 bool intersection(Point o1, double r1, Point o2, double r2, Point& p1, Point& p2) { 31 double d = dis(o1, o2); 32 if (d < fabs(r1 - r2) - eps || d > r1 + r2 + eps) { 33 return false; 34 } 35 double cosa = (sqr(r1) + sqr(d) - sqr(r2)) / (2 * r1 * d); 36 double sina = sqrt(max(0.0, 1.0 - sqr(cosa))); 37 p1 = p2 = o1; 38 p1.x += r1 / d * ((o2.x - o1.x) * cosa + (o2.y - o1.y) * -sina); 39 p1.y += r1 / d * ((o2.x - o1.x) * sina + (o2.y - o1.y) * cosa); 40 p2.x += r1 / d * ((o2.x - o1.x) * cosa + (o2.y - o1.y) * sina); 41 p2.y += r1 / d * ((o2.x - o1.x) * -sina + (o2.y - o1.y) * cosa); 42 return true; 43 } 44 45 int find(int x){ 46 if(fa[x] == x) return x; 47 return fa[x] = find(fa[x]); 48 } 49 50 int main(){ 51 int T; scanf("%d",&T); 52 while(T--){ 53 int n; scanf("%d",&n); 54 for(int i = 1;i<=n;++i) scanf("%lf %lf %lf",&c[i].o.x,&c[i].o.y,&c[i].r); 55 for(int i = 1;i<=n;++i) fa[i] = i,st1[i].clear(),st2[i].clear(),E[i]=0; 56 Point p1,p2; 57 for(int i = 2;i<=n;++i){ 58 for(int j = i-1;j>=1;--j){ 59 if(intersection(c[i].o,c[i].r,c[j].o,c[j].r,p1,p2)){ 60 int f = find(j); 61 fa[f] = i; 62 } 63 } 64 } 65 for(int i = 2;i<=n;++i){ 66 for(int j = i-1;j>=1;--j){ 67 if(!intersection(c[i].o,c[i].r,c[j].o,c[j].r,p1,p2)) continue; 68 int f = find(i); 69 st2[f].insert(p1); st2[f].insert(p2); 70 st1[i].insert(p1); st1[i].insert(p2); 71 st1[j].insert(p1); st1[j].insert(p2); 72 } 73 } 74 for(int i = 1;i<=n;++i){ 75 int f = find(i); 76 E[f] += st1[i].size(); 77 } 78 ll ans = 1; 79 for(int i = 1;i<=n;++i){ 80 int f = find(i); 81 if(f != i) continue; 82 ans += (ll)1 - (int)st2[i].size() + E[i]; 83 } 84 printf("%lld\n",ans); 85 } 86 return 0; 87 }