zju2589 不重合的n个圆形成的区域

zju2589 不重合的n个圆形成的区域


  1  /*  
  2   * SOUR:zju2589
  3   * ALGO:computational geomtry 计算平面上不重合的n个圆形成的区域
  4   * 基本的方法,如图所示,将所有圆之间的交点作为点,将在同一个圆上的所有交点之间的弧作
  5   * 为边建立一张有向图,之后可以利用平面图的欧拉定理
  6   *           V - E + F = 2
  7   * 由于V已知,E已知,F就可以求出来了。
  8   * 由于欧拉定理是对一张无向连通图成立的,如果图有多个连通块的时候需要对欧拉定理做一些
  9   * 修改。由于多个有向图的面共享最外边的面,所以设联通块的个数为n
 10   * V - E + F = 2 * n , 但是需要减去n个联通块共享的最大平面
 11   * 所以 F = n + 1 + E - V;
 12   * DATE: 2010年 07月 08日 星期四 14:49:41 CST
 13   * COMM:5
 14   *  */
 15  const   int  N  =   64 ;
 16  const   double  eps  =  1e - 8 ;
 17  int  n, vis[N], g[N][N];
 18  double  r[N];
 19  struct  point_t {
 20       double  x, y;
 21      point_t(){}
 22      point_t( double  a,  double  b){x  =  a, y  =  b;} 
 23  }c[N];
 24 
 25  int  dcmp( double  x) {  return  (x  >  eps)  -  (x  <   - eps);} 
 26  bool   operator   <  (point_t a,point_t b) 
 27  {
 28     if  (dcmp(a.x  -  b.x)) {
 29         return  a.x  <  b.x;
 30    }
 31     return  dcmp(a.y  -  b.y)  <   0 ;
 32  }
 33 
 34  point_t  operator   +  (point_t a, point_t b) {  return  point_t(a.x + b.x, a.y + b.y);}
 35  point_t  operator   -  (point_t a, point_t b) {  return  point_t(a.x - b.x, a.y - b.y);}
 36  double  dist(point_t a, point_t b) {  return  hypot(a.x - b.x, a.y - b.y);}
 37  double  sqr( double  x) {  return  x  *  x;}
 38  point_t normal(point_t a) {  return  point_t(a.x  /  hypot(a.x, a.y), a.y  /  hypot(a.x, a.y));}
 39  point_t scale(point_t a,  double  fac) {  return  point_t(a.x  *  fac, a.y  *  fac);}
 40  bool  intersect(point_t c1,  double  r1, point_t c2,  double  r2, point_t  & a, point_t  & b)
 41  {
 42     double  d  =  dist(c1, c2);
 43     if  (d  <  fabs(r1  -  r2)  -  eps  ||  d  >  r1  +  r2  +  eps) {
 44         return   false ;
 45    }
 46     double  len  =  (sqr(r1)  -  sqr(r2)  +  sqr(d))  /   2.0   /  d;
 47     double  h  =  sqrt(sqr(r1)  -  sqr(len));
 48    point_t t  =  normal(c2  -  c1);
 49    point_t p  =  c1  +  scale(t, len);
 50    point_t v  =  scale(point_t( - t.y, t.x), h);
 51    a  =  p  +  v, b  =  p  - v;
 52     return   true ;
 53  }
 54 
 55  void  init()
 56  {
 57     int  i;
 58    memset(g,  0 sizeof (g));
 59    memset(vis,  0 sizeof (vis));
 60     for  (i  =   0 ;i  <  n;i ++ ) {
 61        g[i][i]  =   1 ;
 62    }
 63  }
 64 
 65  int  main()
 66  {
 67     int  testcase, i, j, k;
 68    scanf( " %d " & testcase);
 69     while  (testcase -- ) {
 70        scanf( " %d " & n);
 71         set   < point_t >  allpoint, p[ 64 ];
 72         for  (i  =   0 ;i  <  n;i ++ ) {
 73            scanf( " %lf %lf %lf " & c[i].x,  & c[i].y,  & r[i]);
 74        }
 75        init();
 76         for  (i  =   0 ;i  <  n;i ++ ) {
 77             for  (j  =  i  +   1 ;j  <  n;j ++ ) {
 78                point_t a, b;
 79                 if  (intersect(c[i], r[i], c[j], r[j], a, b)) {
 80                    allpoint.insert(a), allpoint.insert(b);
 81                    p[i].insert(a), p[i].insert(b);
 82                    p[j].insert(a), p[j].insert(b);
 83                    g[i][j]  =  g[j][i]  =   1 ;
 84                }
 85            }
 86        }
 87         for  (k  =   0 ;k  <  n;k ++ ) {
 88             for  (i  =   0 ;i  <  n;i ++ ) {
 89                 for  (j  =   0 ;j  <  n;j ++ ) {
 90                    g[i][j]  |=  g[i][k]  &  g[k][j];
 91                }
 92            }
 93        }
 94         int  f  =   1 ;
 95         for  (i  =   0 ;i  <  n;i ++ ) {
 96            f  +=  p[i].size();
 97             if  ( ! vis[i]) {
 98                f  +=   1 ;
 99                 for  (j  =   0 ;j  <  n;j ++ ) {
100                    vis[j]  |=  g[i][j];
101                }
102            }
103        }
104        f  -=  allpoint.size();
105        printf( " %d\n " , f);
106    } 
107     return   0 ;
108  }
109 
110 

你可能感兴趣的:(zju2589 不重合的n个圆形成的区域)