现在的位置: 首页 > 综合 > 正文

poj 2284(欧拉公式的推广:线段分平面成几个区域:n+m-r==2)

2018年05月01日 ⁄ 综合 ⁄ 共 1868字 ⁄ 字号 评论关闭

欧拉公式:如果G是一个阶为n,边数为m 且含有R个区域的联通平面图,则恒有等式:n-m+R==2;

推广:具有k 个联通分支的平面图G,有: n-m+R==k+1其中n,m,r,分别为阶数,边数,和区域数。

回到题目:给出一些点 ,首尾相连,求分成的区域数

#include<cstdio>
#include<cstring>
#include<stdlib.h>
#define inf 0xffffff
#include<iostream>
#include<cmath>
#define NUM 22
#include <algorithm>
using namespace std;


const double eps=1e-6;
struct point
{
    double x,y;
    point(double a=0,double b=0)
    {x=a;y=b;}
};
bool operator< (point a, point b)
{
    return a.x<b.x||a.x==b.x&&a.y<b.y;
}
bool operator == (point a,point b)
{
    return abs(a.x-b.x)<eps&&abs(a.y-b.y)<eps;
}
struct Lineseg
{
    point s,e;
    Lineseg(point a, point b){s=a;e=b;}
};
struct Line
{
    double a,b,c;
};
bool online(Lineseg L,point p)//判断p是否在线段L上
{
  return abs((L.e.x-L.s.x)*(p.y-L.s.y)-(p.x-L.s.x)*(L.e.y-L.s.y))<eps&&(p.x-L.s.x)*(p.x-L.e.x)<eps&&(p.y-L.s.y)*(p.y-L.e.y)<eps;
}
Line Makeline(Lineseg tmp)//线段L变成L
{
   Line L;
   int x1=tmp.s.x;
   int y1=tmp.s.y;
   int x2=tmp.e.x;
   int y2=tmp.e.y;
   if(y2-y1>0)
   {
     L.a=(y2-y1);
     L.b=(x1-x2);
     L.c=(x2*y1-x1*y2);
   }
   else
   {
     L.a=(y1-y2);
     L.b=(x2-x1);
     L.c=(x1*y2-x2*y1);
   }
   return L;
}
bool Lineinter(Line x,Line y,point &q)//直线X,Y相交于点q
{
  double d=x.a*y.b-y.a*x.b;
  if(abs(d)<eps)
  return false;
  q.x=(y.c*x.b-x.c*y.b)/d;
  q.y=(y.a*x.c-x.a*y.c)/d;
  return 1;
}


bool Lineseginter(Lineseg aa,Lineseg bb,point &q)//线段aa,bb如果相交则返回交点q
{
   Line a,b;
   a=Makeline(aa);
   b=Makeline(bb);
   if(Lineinter(a,b,q))
    return online(aa,q)&&online(bb,q);
   else
   return false;
}
bool cmp(point a ,point b)
{
    if(a.x==b.x)
    return a.y<b.y;
    else
    return a.x<b.x;
}
point p[96003];
point inter[98000];
int N;
int main()
{
    int m,n;
    int T=0;
  while(scanf("%d",&N),N)
  {
      m=n=0;
      int cnt=0;
      for(int i=0;i<N;i++)
        scanf("%lf %lf",&p[i].x,&p[i].y);
      for(int i=0;i<N;i++)
      {
          for(int j=0;j<N;j++)
          {
              Lineseg L1(p[i],p[(i+1)%N]),L2(p[j],p[(j+1)%N]);
              point q;
              if(Lineseginter(L1,L2,q))
                inter[cnt++]=q;
          }
      }
      sort(inter,inter+cnt,cmp);
      n=unique(inter,inter+cnt)-inter;//去重复的点
      for(int i=0;i<n;i++)
      {
          for(int j=0;j<N;j++)
          {
              Lineseg t(p[j],p[(j+1)%N]);
              if(online(t,inter[i])&&!(t.s==inter[i]))m++;
          }
      }
      T++;
      printf("Case %d: There are %d pieces.\n",T,m+2-n);//欧拉定理
  }
 return 0;
}

 

抱歉!评论已关闭.