题意:
给出一系列线段,判断某两个线段是否连通.
思路:
根据线段相交情况建立并查集, 在同一并查集中则连通.
(第一反应是强连通分量...实际上只要判断共存即可, 具体的方向啊是没有关系的..)
并查集合并的时候是根节点合并.
快速排斥试验不是必需的, 大规模数据可能是个优化吧.
跨立试验注意共线的情况.
共线判断注意与y 轴平行的情况.
#include <cstdio> #include <cstring> #include <cmath> using namespace std; const double EPS = 1e-6; const int INF = 0x3f3f3f3f; const int MAXN = 15; typedef struct node { double x,y; }point; point a[MAXN],b[MAXN]; bool adj[MAXN][MAXN]; int n; int max(int a, int b) { int diff = b - a; return b - (diff & (diff>>31)); } int min(int a, int b) { int diff = b - a; return a + (diff & (diff>>31)); } int fa[MAXN]; int FindSet(int x) { if(x==fa[x]) return fa[x]; return fa[x] = FindSet(fa[x]); } int dcmp(double p) { if(fabs(p)<EPS) return 0; return p>0?1:-1; } double det(double x1, double y1, double x2, double y2) { return x1*y2 - x2*y1; } double cross(point A, point B, point P) { return det(B.x - A.x, B.y - A.y, P.x - A.x, P.y - A.y); } bool ck(point A, point B, point C, point D) { int min1x = min(A.x,B.x), min2x = min(C.x,D.x); int max1x = max(A.x,B.x), max2x = max(C.x,D.x); int min1y = min(A.y,B.y), min2y = min(C.y,D.y); int max1y = max(A.y,B.y), max2y = max(C.y,D.y); /*if(max(max1x,max2x)-min(min1x,min2x)>(max1x-min1x)+(max2x+min2x) || max(max1y,max2y)-min(min1y,min2y)>(max1y-min1y)+(max2y+min2y)) return false;*/ int a = dcmp(cross(A, B, C)); int b = dcmp(cross(A, B, D)); if(!a && !b) return ( max(max1x,max2x)-min(min1x,min2x)<=(max1x-min1x)+(max2x-min2x) && max(max1y,max2y)-min(min1y,min2y)<=(max1y-min1y)+(max2y-min2y) ); int c = dcmp(cross(C, D, A)); int d = dcmp(cross(C, D, B)); return (( a* b <= 0) && ( c* d <= 0));//规范或不规范相交 } void BuildSet() { for(int i=1;i<=n;i++) { fa[i] = i; } for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { if(ck(a[i],b[i],a[j],b[j])) { int fi = FindSet(i), fj = FindSet(j);//并查集写错了= = fa[fi] = fj; } } } } bool check(int a, int b) { return (FindSet(a)==FindSet(b)); } int main() { int x, y; while(scanf("%d",&n)==1 && n) { for(int i=1;i<=n;i++) scanf("%lf %lf %lf %lf",&a[i].x,&a[i].y,&b[i].x,&b[i].y); BuildSet(); while(scanf("%d %d",&x,&y)==2 && (x+y)) { if(check(x, y)) printf("CONNECTED\n"); else printf("NOT CONNECTED\n"); } } }