平面图中的欧拉定理

来源:互联网 发布:伞齿轮参数计算软件 编辑:程序博客网 时间:2024/05/01 07:32

定理:设G为任意的连通的平面图,则v-e+f=2,v是G的顶点数,e是G的边数,f是G的面数。

题目描述:给出一个一笔画图形的n个节点的坐标,请你求解这个图形把平面分成了几个面
一笔画图形一个是把图上所有的边仅且遍历一次的封闭连通图。
分析:求面的问题就分解为求顶点个数与边条数的问题。
点的求法:遍历每条线段,如果是规范相交,则将该点存入V[]数组中。最后对V[]数组进行排序,使用STL中的unique()函数对求出来的交点进行去重处理。
边的求法:遍历每个交点和每条线段,如果交点在线段上,边数加一

//欧拉定理#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <string.h>#include <vector>using namespace std;struct point{    double x, y;    point(double x = 0.0, double y = 0.0) :x(x), y(y) {};};typedef point Vector;const double eps = 1e-8;//判断double类型(x)与0的大小int dcmp(double x) { if (fabs(x)<eps) return 0; return (x<0) ? -1 : 1; }//向量的运算符重载Vector operator + (Vector A, Vector B) { return Vector(A.x + B.y, A.y + B.y); }Vector operator - (Vector A, Vector B) { return Vector(A.x - B.y, A.y - B.y); }Vector operator * (Vector A, double p) { return Vector(p * A.x, p * A.y); }Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); }bool operator < (const point& a, const point& b) {//判断a点是否小于b点    return a.x < b.x || (a.x == b.x && a.y < b.y);}bool operator == (const point& a, const point &b) {//判断两个点是否相等    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;}//向量的运算double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }//向量的点乘double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }//向量的叉积 //判断规范相交bool SegmentProperIntersection(point a1, point a2, point b1, point b2){    double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1);    double c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);    return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;}//两直线交点(参数法)point GetLineIntersection(point P, Vector v, point Q, Vector w) {    Vector u = P - Q;    double t = Cross(w, u) / Cross(v, w);    return P + v*t;}//判断点p是否在线段a1a2上(叉乘=0;点乘<0)bool OnSegment(point p, point a1, point a2){    return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p))<0;}const int maxn = 300 + 10;point P[maxn], V[maxn * maxn];int main(){    int n, kase = 0, c, e;    while (~scanf("%d", &n) && n) {        for (int i = 0; i < n; i++) {            scanf("%d%d", &P[i].x, &P[i].y);            V[i] = P[i];        }        c = n - 1; e = n - 1;        for (int i = 0; i < c; i++)//遍历每个点            for (int j = i + 1; j < c; j++)                if (SegmentProperIntersection(P[i], P[i + 1], P[j], P[j + 1]))//如果是规范相交                    V[c++] = GetLineIntersection(P[i], P[i + 1] - P[i], P[j], P[j + 1] - P[j]);//把交点存入V[]中        sort(V, V + c);        c = unique(V, V + c) - V;//把重复元素放到数组后面,c为(去重后)交点的个数        for (int i = 0; i < c; i++)//遍历每个交点            for (int j = 0; j < n - 1; j++)//遍历每条线段                if (OnSegment(V[i], P[j], P[j + 1])) e++;//如果交点在线段上,边数加一        printf("Case %d: There are %d pieces.\n", ++kase, e + 2 - c);    }}
0 0
原创粉丝点击