码迷,mamicode.com
首页 > 其他好文 > 详细

poj2284 That Nice Euler Circuit(欧拉公式)

时间:2016-09-21 00:00:31      阅读:336      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:poj2284 That Nice Euler Circuit

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

欧拉公式的推广: 对于具有k(k≥2)个连通分支的平面图G,有:n-m+r=k+1。

题意:给出连通平面图的各顶点,求这个欧拉回路将平面分成多少区域。

题解:根据平面图的欧拉定理“n-m+r=2”来求解区域数r。

顶点个数n:两两线段求交点,每个交点都是图中的顶点。

边数m:在求交点时判断每个交点落在第几条边上,如果一个交点落在一条边上,这条边就分裂成两条边,边数加一。

学习之路漫漫啊。。

看懂了书上例题再敲的,我基础差就是累哦、、

技术分享
 1 #include<cstdio>
 2 #include<cmath>
 3 #include<queue>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 const double eps = 1e-9;
 9 const int N = 90001;
10 
11 struct point{//
12     double x, y;
13     point(double _x = 0, double _y = 0): x(_x), y(_y){}
14 };
15 
16 struct lineSegment{//线段
17     point s, e;
18     lineSegment(point s, point e): s(s), e(e){}
19 };
20 struct line{//直线
21     double a, b, c;
22 };
23 bool operator < (point p1, point p2){
24     return p1.x < p2.x || p1.x == p2.x && p1.y < p2.y;
25 }
26 bool operator == (point p1, point p2){
27     return abs(p1.x - p2.x) < eps && abs(p1.y - p2.y) < eps;
28 }
29 bool onLine(lineSegment l, point p){//判断点是否在线段上
30     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 //点在直线上
31     && (p.x - l.s.x) * (p.x - l.e.x) < eps && (p.y - l.s.y) * (p.y - l.e.y) < eps;//点在线段内
32 }
33 line make_Line(point p1, point p2){//将线段延长为直线
34     line l;
35     l.a = (p2.y > p1.y) ? p2.y - p1.y : p1.y - p2.y;
36     l.b = (p2.y > p1.y) ? p1.x - p2.x : p2.x - p1.x;
37     l.c = (p2.y > p1.y) ? p1.y * p2.x - p1.x * p2.y : p1.x * p2.y - p1.y * p2.x;
38     return l;
39 }
40 //判断直线是否相交,并求交点p
41 bool line_Intersect(line l1, line l2, point &p){
42     double d = l1.a * l2.b - l2.a * l1.b;
43     if(abs(d) < eps) return false; //叉积为0,平行或重合
44     p.x = (l2.c * l1.b - l1.c * l2.b) /d;
45     p.y = (l2.a * l1.c - l1.a * l2.c) /d;
46     return true;
47 }
48 //判断线段是否相交
49 bool lineSegment_Intersect(lineSegment l1, lineSegment l2, point &p){
50     line a, b;
51     a = make_Line(l1.s, l1.e);//将线段延长为直线
52     b = make_Line(l2.s, l2.e);
53     if(line_Intersect(a, b, p))//如果直线相交
54         //判断直线交点是否在线段上,是则线段相交
55         return onLine(l1, p) && onLine(l2, p);
56     else return false;
57 }
58 
59 point p[N], intersection[N];
60 int n, m;
61 
62 int main(){
63     int nn, i, j, kase = 1;
64     while(scanf("%d", &nn) && nn){
65         n = m = 0;
66         for(i = 0; i < nn; ++i)
67             scanf("%lf %lf", &p[i].x, &p[i].y);
68         for(i = 0; i < nn; ++i){
69             for(j = 0; j < nn; ++j){
70                 if(i == j) continue;
71                 lineSegment l1(p[i], p[(i+1)%nn]), l2(p[j], p[(j+1)%nn]);
72                 point v;
73                 if(lineSegment_Intersect(l1, l2, v))
74                     intersection[n++] = v;//记录交点
75             }
76         }
77         sort(intersection , intersection + n);
78         //移除重复点
79         n = unique(intersection, intersection + n) - intersection;
80         for(i = 0; i < n; ++i){
81             for(j = 0; j < nn; ++j){
82                 lineSegment l3(p[j], p[(j+1)%nn]);
83                 //若有交点落在边上,则该边分裂成两条边
84                 if(onLine(l3, intersection[i]) && !(l3.s == intersection[i]))
85                     m++;
86             }
87         }
88         printf("Case %d: There are %d pieces.\n", kase++, 2 + m - n);
89     }
90     return 0;
91 }
View Code

 

poj2284 That Nice Euler Circuit(欧拉公式)

标签:

原文地址:http://www.cnblogs.com/GraceSkyer/p/5891044.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!