Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 2942 | Accepted: 1331 |
Descriptionios
Input算法
Outputless
Sample Inputide
7 1 6 3 3 4 6 4 9 4 5 6 7 1 4 3 5 3 5 5 5 5 2 6 3 5 4 7 2 1 4 1 6 3 3 6 7 2 3 1 3 0 0 2 0 2 0 0 0 0 0 1 1 1 2 2 1 2 0 0 0
Sample Outputspa
CONNECTED NOT CONNECTED CONNECTED CONNECTED NOT CONNECTED CONNECTED CONNECTED CONNECTED CONNECTED
Sourcecode
給出二維平面上的一些線段,以後有一些詢問,判斷各對線段是不是連通的blog
因爲線段數比較少,能夠先判斷一遍每對線段之間是不是直接相連的,以後再用Floyd算法找出兩條線段之間是否能夠間接相連,最後對每組詢問,能夠直接O(1)給出答案ip
判斷兩條線段是否有交點能夠先求出兩條線段所在直線的交點,以後再判斷交點是否在兩條線段上。rem
在幾何問題中,運用向量的內積和外積進行計算是很是方便的。對於二維向量p1=(x1,y1)和p2=(x2,y2),咱們定義內積p1·p2=x1*x2+y1*y2,外積p1×p2=x1*y2-y1*x2。要判斷點q是否在線段p1-p2上,只要先用外積跟據是否有(p1-q)×(p2-q)=0來判斷點q是否在直線p1-p2上,再利用內積根據是否有(p1-q)·(p2-q)≤0來判斷點q是否落在p1-p2之間。get
此題中還要注意邊界狀況,數據中可能存在兩條線段在同一條直線上(即它們是平行的,或者說是共線的),但它們可能在端點處有公共點,這裏咱們要經過檢查端點是否在另外一條線段上來判斷
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #define MAX_N 15 6 7 using namespace std; 8 9 double EPS=1e-10; 10 11 double add(double a,double b) 12 { 13 if(fabs(a+b)<EPS*(fabs(a)+fabs(b))) 14 return 0; 15 return a+b; 16 } 17 18 struct P 19 { 20 double x,y; 21 22 P(){} 23 24 P(double x,double y):x(x),y(y){} 25 26 P operator + (P p) 27 { 28 return P(add(x,p.x),add(y,p.y)); 29 } 30 31 P operator - (P p) 32 { 33 return P(add(x,-p.x),add(y,-p.y)); 34 } 35 36 P operator * (double d) 37 { 38 return P(x*d,y*d); 39 } 40 41 //內積 42 double dot(P p) 43 { 44 return add(x*p.x,y*p.y); 45 } 46 47 //外積 48 double det(P p) 49 { 50 return add(x*p.y,-y*p.x); 51 } 52 }; 53 54 //判斷點q是否在線段p1-p2上 55 bool on_seg(P p1,P p2,P q) 56 { 57 return (p1-q).det(p2-q)==0&&(p1-q).dot(p2-q)<=0; 58 } 59 60 //計算直線p1-p2與直線q1-q2的交點 61 P intersection(P p1,P p2,P q1,P q2) 62 { 63 return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1)); 64 } 65 66 int n; 67 P p[MAX_N],q[MAX_N]; 68 bool g[MAX_N][MAX_N]; 69 70 void solve() 71 { 72 for(int i=0;i<n;i++) 73 { 74 g[i][i]=true; 75 for(int j=0;j<i;j++) 76 { 77 //判斷木棍i和木棍j是否有公共點 78 if((p[i]-q[i]).det(p[j]-q[j])==0) 79 { 80 //平行時,判斷是否可能在端點處有交點 81 g[i][j]=g[j][i]=on_seg(p[i],q[i],p[j])||on_seg(p[i],q[i],q[j])||on_seg(p[j],q[j],p[i])||on_seg(p[j],q[j],q[i]); 82 } 83 else 84 { 85 //非平行時,先求出兩直線交點再湊數交點是否在兩條線段上 86 P r=intersection(p[i],q[i],p[j],q[j]); 87 g[i][j]=g[j][i]=on_seg(p[i],q[i],r)&&on_seg(p[j],q[j],r); 88 } 89 } 90 } 91 92 //經過Floyd-Warshall算法判斷任意的兩點間是否相連 93 for(int k=0;k<n;k++) 94 for(int i=0;i<n;i++) 95 for(int j=0;j<n;j++) 96 g[i][j]|=g[i][k]&&g[k][j]; 97 } 98 99 int main() 100 { 101 while(scanf("%d",&n)&&n) 102 { 103 for(int i=0;i<n;i++) 104 scanf("%lf %lf %lf %lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y); 105 solve(); 106 int a,b; 107 while(scanf("%d %d",&a,&b)&&(a||b)) 108 puts(g[a-1][b-1]?"CONNECTED":"NOT CONNECTED"); 109 } 110 111 return 0; 112 }