}/******************************************************************************************** Date:2009-3-27 Place:HIT Author:Min,Liu Function:桌面上有n个吸管,判断任意两根是否相交 Main Method:计算几何 并查集 ********************************************************************************************/ #include <iostream> #include <stdio.h> using namespace std; struct point { int x; int y; }; struct line { point a; point b; }; point duandian1[N];//用于存一条线的一个端点(x1,y1) point duandian2[N];//用于存一条线的;另一个端点(x2,y2) const int N = 30010; int set[N], rank[N]; //并查集的初始化,所有结点的父节点是自己而且秩为1 void init(int n) { for (int i = 0; i <= n; i++) { set[i] = i; rank[i] = 1; } } //寻找根 int root(int i) { if (set[i] == i) return i; set[i] = root(set[i]); return set[i]; } //合并,这个程序是合并线段,一个线段有自己的号码代表自己 void join(int i, int j) { i = root(i); j = root(j); if (i == j) return; if (i<j) { set[j] = i; } else set[i] = j; } void Input( int n ) { int i; for(i=1;i<=n;i++) { scanf("%d %d", &duandian1[i].x, &duandian1[i].y ); scanf("%d %d", &duandian2[i].x, &duandian2[i].y ); } } void ceshi() { int i; int j; while(scanf("%d %d", &i, &j)==2 ) { if(i==0&&j==0) break; if(root(i)==root(j)) printf("CONNECTED/n"); else printf("NOT CONNECTED/n"); } } //判断不在两边时,是不是属于一个端点恰好在另一个线段上 int onSegment(point* pi, point* pj, point* pk) { int minx, miny, maxx, maxy; if (pi->x > pj->x) { minx = pj->x; maxx = pi->x; } else { minx = pi->x; maxx = pj->x; } if (pi->y > pj->y) { miny = pj->y; maxy = pi->y; } else { miny = pi->y; maxy = pj->y; } if (minx <= pk->x && pk->x <= maxx && miny <= pk->y && pk->y <= maxy) return 1; else return 0; } //计算两个向量的叉积 int crossProduct(line* v1, line* v2) { line vt1, vt2; int result = 0; vt1.a.x = 0; vt1.a.y = 0; vt1.b.x = v1->b.x - v1->a.x; vt1.b.y = v1->b.y - v1->a.y; vt2.a.x = 0; vt2.a.y = 0; vt2.b.x = v2->b.x - v2->a.x; vt2.b.y = v2->b.y - v2->a.y; result = vt1.b.x * vt2.b.y - vt2.b.x * vt1.b.y; return result; } //三个点求出两个向量,再调用crossProduct函数算叉积,从而知道三个点的位置 int direction(point* pi, point* pj, point* pk) { line l1, l2; l1.a.x = 0; l1.a.y = 0; l1.b.x = pk->x - pi->x; l1.b.y = pk->y - pi->y; l2.a.x = 0; l2.a.y = 0; l2.b.x = pj->x - pi->x; l2.b.y = pj->y - pi->y; return crossProduct(&l1, &l2); } //中心函数,通过调用其他函数判断两个线段是否相交 int segmentIntersect(point* p1, point* p2, point* p3, point* p4) { int d1 = direction(p3, p4, p1); int d2 = direction(p3, p4, p2); int d3 = direction(p1, p2, p3); int d4 = direction(p1, p2, p4); if (d1 * d2 < 0 && d3 * d4 < 0) return 1; else if (!d1 && onSegment(p3, p4, p1)) return 1; else if (!d2 && onSegment(p3, p4, p2)) return 1; else if (!d3 && onSegment(p1, p2, p3)) return 1; else if (!d4 && onSegment(p1, p2, p4)) return 1; else return 0; } int main() { int n; while( scanf("%d",&n)==1 && n ) { init( n ); int i; int j; Input(n); for(i=1;i<=n;i++) { for(j=1;j<i;j++) { int flag=segmentIntersect( &duandian1[i], &duandian2[i], &duandian1[j], &duandian2[j] ); if(flag==1) join(i,j); else ; } } //for(i=1;i<=7;i++) // printf("root[%d]=%d/n",i,root(i)); ceshi(); } return 0; } 第一次写计算几何,写得很辛苦,继续努力!!